[英]insertion in a self referenced table
如果我有一張桌子
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可能需要知道並且是常量,但對於林(具有預先未知的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
如果需要對第一個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;
對於樹中的根節點,似乎NOT NULL
約束不正確。 它根本就沒有父母。 因此,從一開始就打破了ParentID
為NOT NULL
的假設。
我建議你讓它可以為空並在ParentID
上添加一個索引來驗證只有一個值為NULL
:
create unique nonclustered index ... on T (ParentID) where (ParentID IS NULL)
在SQL Server中很難強制實現聲音樹結構。 例如,您可以在圖表中獲得多個根或循環。 很難對所有這些進行驗證,目前還不清楚是否值得付出努力。 根據具體情況,可能會這樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.