插入自引用表

Nez*_*eli 7 sql sql-server

如果我有一张桌子

Table
{
ID int primary key identity,
ParentID int not null foreign key references Table(ID)
}
Run Code Online (Sandbox Code Playgroud)

如何将第一行插入表中?

从业务逻辑的角度来看,不应该删除ParentID上的空约束.

Ser*_*lov 5

在SQL Server中,一个简单的INSERT将执行:

create table dbo.Foo
(
ID int primary key identity,
ParentID int not null foreign key references foo(ID)
)
go

insert dbo.Foo (parentId) values (1)

select * from dbo.Foo
Run Code Online (Sandbox Code Playgroud)

结果是

    ID          ParentID
----------- -----------
    1           1
Run Code Online (Sandbox Code Playgroud)

如果您尝试插入的值与您的标识种子不同,则插入将失败.

更新:

关于上下文是什么(即代码应该在实时生产系统中工作还是仅仅是数据库设置脚本)的问题并不是很清楚,而且从注释中看起来很难编码ID可能不是一个选项.虽然上面的代码通常可以在数据库初始化脚本中正常工作,其中层次结构根ID可能需要知道并且是常量,但对于林(具有预先未知的ID的多个根),以下代码应按预期工作:

create table dbo.Foo
(
ID int primary key identity,
ParentID int not null foreign key references foo(ID)
)
go

insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))
Run Code Online (Sandbox Code Playgroud)

然后可以像往常一样查询最后一个身份(SCOPE_IDENTITY等等).为了解决@ usr的问题,代码实际上是事务安全的,如下例所示:

insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))
insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))
insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))

select * from dbo.Foo

select IDENT_CURRENT('dbo.Foo')
begin transaction   
    insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))
    rollback

select IDENT_CURRENT('dbo.Foo')

insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))

select * from dbo.Foo
Run Code Online (Sandbox Code Playgroud)

结果:

ID          ParentID
----------- -----------
1           1
2           2
3           3

currentIdentity
---------------------------------------
3

currentIdentity
---------------------------------------
4

ID          ParentID
----------- -----------
1           1
2           2
3           3
5           5
Run Code Online (Sandbox Code Playgroud)