限制数据库树深度

发布于 2024-11-18 23:54:52 字数 214 浏览 3 评论 0原文

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

实体关系
复合密钥
孩子ID
父 id

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

Typically when I represent a parent child hierarchy I have a table as follows (I might also add additional depth columns to speed things up), where parents and children are both foreign key relationships to rows from the same entity table.

Entity Relationships
composite pkey
child id
parent id

What I am trying to figure out is how to limit the depth of the tree to one. In other words, if somebody is the parent of a child, how to I prevent that parent from being a child in itself, so it is impossible to have grandparents or even further?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淑女气质 2024-11-25 23:54:52

根据您的 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

Depending on your RDBMS, you can handle something like this in an INSERT/UPDATE trigger. For simply restricting a parent to not also be a child it shouldn't be too bad (although I hate using triggers any more than necessary). If you were trying to limit to a certain number of levels (say 100) then you might start to run into performance issues.

In MS SQL Server you can also use user-defined functions in constraints. There are limits however, so I don't know if it would work here. I'll try to test it though.

EDIT:

I just tested this on MS SQL Server 2008 and it looks like it works correctly:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文