如果我有桌子
Table
{
ID int primary key identity,
ParentID int not null foreign key references Table(ID)
}
如何将第一行插入表中?
从业务逻辑的角度来看,不应该删除ParentID上的空约束。
答案 0 :(得分: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
结果
ID ParentID
----------- -----------
1 1
如果您尝试插入的值与您的身份种子不同,则插入将失败。
更新:
关于上下文是什么(即代码应该在实时生产系统中工作还是仅仅是数据库设置脚本)的问题并不是很明确,而且从注释看起来硬编码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'))
然后可以照常查询最后一个身份(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
结果:
ID ParentID
----------- -----------
1 1
2 2
3 3
currentIdentity
---------------------------------------
3
currentIdentity
---------------------------------------
4
ID ParentID
----------- -----------
1 1
2 2
3 3
5 5
答案 1 :(得分:2)
如果您需要为第一个ID使用显式值,则在插入第一个记录时,可以禁用IDENTITY值的检查(请参阅:MSDN: SET IDENTITY_INSERT (Transact-SQL))。
这是一个证明这一点的例子:
CREATE TABLE MyTable
(
ID int PRIMARY KEY IDENTITY(1, 1),
ParentID int NOT NULL,
CONSTRAINT MyTable_ID FOREIGN KEY (ParentID) REFERENCES MyTable(ID)
);
SET IDENTITY_INSERT MyTable ON;
INSERT INTO MyTable (ID, ParentID)
VALUES (1, 1);
SET IDENTITY_INSERT MyTable OFF;
WHILE @@IDENTITY <= 5
BEGIN
INSERT INTO MyTable (ParentID)
VALUES (@@IDENTITY);
END;
SELECT *
FROM MyTable;
IF OBJECT_ID('MyTable') IS NOT NULL
DROP TABLE MyTable;
答案 2 :(得分:2)
对于树中的根节点,似乎NOT NULL
约束不正确。它根本就没有父母。因此,ParentID
为NOT NULL
的假设从一开始就被打破了。
我建议您将其设为可为空并在ParentID
上添加索引,以验证只有一个值NULL
:
create unique nonclustered index ... on T (ParentID) where (ParentID IS NULL)
在SQL Server中强制实施声音树结构很困难。例如,您可以在图表中获得多个根或循环。很难对所有这些进行验证,目前还不清楚是否值得付出努力。根据具体情况,可能会这样。