8

如果我有一张桌子

Table
{
ID int primary key identity,
ParentID int not null foreign key references Table(ID)
}

如何将第一行插入表中?

从业务逻辑的角度来看,不应删除对 ParentID 的非空约束。

4

3 回答 3

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 可能需要已知且恒定的 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
于 2012-11-10T09:17:53.193 回答
2

NOT NULL对于树中的根节点,该约束似乎不正确。它根本没有父母。所以这个假设从一开始ParentIDNOT NULL被打破了。

我建议您将其设为可空并添加一个索引ParentID以验证是否只有一个具有 value NULL

create unique nonclustered index ... on T (ParentID) where (ParentID IS NULL)

在 SQL Server 中很难强制执行健全的树形结构。例如,您可以在图中获得多个根或循环。很难验证所有这些,也不清楚是否值得付出努力。可能是这样,取决于具体情况。

于 2012-11-10T12:45:09.257 回答
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;
于 2012-11-10T09:18:46.700 回答