通常,当我表示父子层次结构时,我有一个表如下(我可能还会添加其他深度列以加快速度),其中父项和子项都是来自同一实体表的行的外键关系。
实体关系
复合p
儿童身份
父母身份
我想弄清楚的是如何将树的深度限制为一个。换句话说,如果有人是孩子的父母,如何防止父母本身成为孩子,那么祖父母甚至不可能进一步生活?
答案 0 :(得分:1)
根据您的RDBMS,您可以在INSERT / UPDATE触发器中处理类似的事情。为了简单地限制父母也不是一个孩子,它不应该太糟糕(虽然我讨厌使用触发器超过必要)。如果您尝试限制到一定数量的级别(比如100),那么您可能会遇到性能问题。
在MS SQL Server中,您还可以在约束中使用用户定义的函数。但是有限制,所以我不知道它是否适用于此。我会尝试测试它。
修改强>
我刚刚在MS SQL Server 2008上对此进行了测试,看起来它的工作正常:
CREATE FUNCTION dbo.Is_Child (@parent_id INT) RETURNS BIT
AS
BEGIN
DECLARE @return BIT
IF EXISTS (SELECT * FROM dbo.Test_Trees WHERE child_id = @parent_id)
SET @return = 1
ELSE
SET @return = 0
RETURN @return
END
GO
CREATE TABLE dbo.Test_Tree_Objects (
my_id INT NOT NULL,
CONSTRAINT PK_Test_Tree_Objects PRIMARY KEY CLUSTERED (my_id)
)
CREATE TABLE dbo.Test_Trees (
my_id INT NOT NULL IDENTITY,
parent_id INT NOT NULL CHECK (dbo.Is_Child(parent_id) = 0),
child_id INT NOT NULL,
CONSTRAINT PK_Test_Trees PRIMARY KEY CLUSTERED (my_id),
CONSTRAINT FK_Test_Trees_parent_id FOREIGN KEY (parent_id) REFERENCES dbo.Test_Tree_Objects (my_id),
CONSTRAINT FK_Test_Trees_child_id FOREIGN KEY (child_id) REFERENCES dbo.Test_Tree_Objects (my_id)
)
GO
INSERT INTO dbo.Test_Tree_Objects (my_id) VALUES (1), (2), (3), (4), (5)
GO
INSERT INTO dbo.Test_Trees (parent_id, child_id) VALUES (1, 2)
INSERT INTO dbo.Test_Trees (parent_id, child_id) VALUES (2, 3)
DROP TABLE dbo.Test_Trees
DROP TABLE dbo.Test_Tree_Objects
DROP FUNCTION dbo.Is_Child
GO