Jer*_*oen 10 sql-server-2008 constraint hierarchy
假设我们有一个对自身有外键约束的表,如下所示:
CREATE TABLE Foo
(FooId BIGINT PRIMARY KEY,
ParentFooId BIGINT,
FOREIGN KEY([ParentFooId]) REFERENCES Foo ([FooId]) )
INSERT INTO Foo (FooId, ParentFooId)
VALUES (1, NULL), (2, 1), (3, 2)
UPDATE Foo SET ParentFooId = 3 WHERE FooId = 1
Run Code Online (Sandbox Code Playgroud)
该表将有以下记录:
FooId ParentFooId
----- -----------
1 3
2 1
3 2
Run Code Online (Sandbox Code Playgroud)
在某些情况下,这种设计可能有意义(例如典型的“员工-老板-员工”关系),并且无论如何:我处于我的模式中有这种情况的情况。
不幸的是,这种设计允许数据记录中的循环,如上例所示。
那么我的问题是:
对于这个问题的第 (2) 部分,可能需要提及的是,我希望我的表中只有数百或在某些情况下可能有数千条记录,通常嵌套的深度不会超过大约 5 到 10 级。
附注。微软 SQL Server 2008
2012 年 3 月 14 日更新
有几个很好的答案。我现在已经接受了帮助我理解提到的可能性/可行性的那个。不过,还有其他几个很好的答案,其中一些还提供了实施建议,因此,如果您带着相同的问题来到这里,请查看所有答案;)
小智 7
我已经看到了两种主要的强制执行方式:
CREATE TABLE Foo
(FooId BIGINT PRIMARY KEY,
ParentFooId BIGINT,
FooHierarchy VARCHAR(256),
FOREIGN KEY([ParentFooId]) REFERENCES Foo ([FooId]) )
Run Code Online (Sandbox Code Playgroud)
FooHierarchy 列将包含如下值:
"|1|27|425"
Run Code Online (Sandbox Code Playgroud)
数字映射到 FooId 列的位置。然后,您将强制 Hierarchy 列以“|id”结尾,并且字符串的其余部分与 PARENT 的 FooHieratchy 匹配。
SQL Server 2008 有一个名为HierarchyID的新数据类型,它为您完成所有这些工作。
它的操作原理与 OLD 方式相同,但它由 SQL Server 有效处理,适合用作“ParentID”列的替换。
CREATE TABLE Foo
(FooId BIGINT PRIMARY KEY,
FooHierarchy HIERARCHYID )
Run Code Online (Sandbox Code Playgroud)
这是可能的:您可以从 CHECK 约束调用标量 UDF,它可以检测任何长度的循环。不幸的是,这种方法极其缓慢且不可靠:您可能会出现误报和漏报。
相反,我会使用物化路径。
另一种避免循环的方法是使用 CHECK(ID > ParentID),这也可能不太可行。
另一种避免循环的方法是再添加两列,LevelInHierarchy 和 ParentLevelInHierarchy,有 (ParentID, ParentLevelInHierarchy) 引用 (ID, LevelInHierarchy),并有一个 CHECK(LevelInHierarchy > ParentLevelInHierarchy)。
归档时间: |
|
查看次数: |
5228 次 |
最近记录: |