7

在下表中,有没有办法确保 PreviousID 始终引用具有匹配 ParentID 的行中的 ID,或者,如果 ParentID 为 null,则它在引用的行中也为 null?

CREATE TABLE MyTable (
  ID int not null identity(1,1) primary key,
  ParentID int null foreign key references MyTable (ID),
  PreviousID int null foreign key reference MyTable (ID),
    foreign key (ParentID, PreviousID) references MyTable (ParentID, ID)
)

一个例子:

+-ID-+-ParentID-+-PreviousID-+  
| 1 | 空 | 空 |  
| 2 | 1 | 空 |  
| 3 | 空 | 2 | <-- 应该是不可能的,应该在 ParentID 为 null 的地方引用 ID
+----+----------+------------+  

有没有办法强制执行?

更新:对于那些想知道的人,复合外键不强制执行此操作,原因如下(从MSDN复制):

FOREIGN KEY 约束可以包含空值;但是,如果复合 FOREIGN KEY 约束的任何列包含空值,则会跳过对构成 FOREIGN KEY 约束的所有值的验证。要确保验证复合 FOREIGN KEY 约束的所有值,请在所有参与列上指定 NOT NULL。

更新:如果它有助于可视化所表示的数据结构,它是一个 B 树,其中具有相同父级的节点组成一个链表。我试图强制链表中的每个“上一个”指针都指向另一个具有相同父节点的节点。在父节点为空的情况下,它应该指向另一个父节点也为空的节点。

4

1 回答 1

1

尝试这个:

CREATE TABLE MyTable ( 
  ID int not null identity(1,1) primary key, 
  ParentID int null foreign key references MyTable (ID), 
  PreviousID int null foreign key references MyTable (ID), 
    foreign key (ParentID, PreviousID) references MyTable (ParentID, ID),
    unique (ParentID, ID),  /* Required for foreign key */
  check (PreviousID is null or ParentID is not null)  /* enforeces requested constraint */
) 

结果:

insert into MyTable (ParentID, PreviousID) values (null, null) /* (1 row(s) affected) */
insert into MyTable (ParentID, PreviousID) values (1, null) /* (1 row(s) affected) */
insert into MyTable (ParentID, PreviousID) values (null, 2) /* The INSERT statement conflicted with the CHECK constraint. 
    The statement has been terminated. */
于 2010-10-13T18:27:22.547 回答