【问题标题】:Restrict database tree depth限制数据库树深度
【发布时间】:2011-07-08 11:57:29
【问题描述】:

通常,当我表示父子层次结构时,我有一个如下表(我还可能添加额外的深度列以加快速度),其中父子节点都是来自同一实体表的行的外键关系。

实体关系
复合密钥
孩子身份证
父 ID

我想弄清楚的是如何将树的深度限制为一。换句话说,如果某人是孩子的父母,我如何防止该父母本身就是孩子,所以不可能有祖父母甚至更远?

【问题讨论】:

  • 这些是您需要在应用程序级别而不是在数据库级别实现的约束
  • 我不喜欢在应用程序级别定义它的想法,因为可能会将不应允许的关系插入到数据库中。我猜这是不可能的,因为您必须在某个时候从表中检索孩子?

标签: sql database tree relationship


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    相关资源
    最近更新 更多