如果我有一张桌子
Table
{
ID int primary key identity,
ParentID int not null foreign key references Table(ID)
}
如何将第一行插入表中?
从业务逻辑的角度来看,不应删除对 ParentID 的非空约束。
如果我有一张桌子
Table
{
ID int primary key identity,
ParentID int not null foreign key references Table(ID)
}
如何将第一行插入表中?
从业务逻辑的角度来看,不应删除对 ParentID 的非空约束。
在 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 可能需要已知且恒定的 DB 初始化脚本中正常工作,但在森林的情况下(几个具有事先未知 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
NOT NULL
对于树中的根节点,该约束似乎不正确。它根本没有父母。所以这个假设从一开始ParentID
就NOT NULL
被打破了。
我建议您将其设为可空并添加一个索引ParentID
以验证是否只有一个具有 value NULL
:
create unique nonclustered index ... on T (ParentID) where (ParentID IS NULL)
在 SQL Server 中很难强制执行健全的树形结构。例如,您可以在图中获得多个根或循环。很难验证所有这些,也不清楚是否值得付出努力。可能是这样,取决于具体情况。
如果您需要对第一个 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;