2011-07-08 12 views
2

通常、親の子階層を表すときは、次のような表があります(処理速度を上げるために深さの列を追加することもできます)。親と子は両方とも同じエンティティの行表。
データベースのツリーの深さを制限する

エンティティの関係
複合PKEY私が把握しようとしています何
子ID
親ID

は1つに、ツリーの深さを制限する方法です。言い換えれば、もし誰かが子供の親であれば、私はその親が子供であることをどうやって防ぐのですか?したがって、祖父母を育てることは不可能です。

+1

これらは、アプリケーションレベルではなく実装する必要が制約されていますデータベースレベルでは – Balanivash

+0

私はアプリケーションレベルでこれを定義する考え方が嫌いでした。なぜなら、許可されてはならないデータベースに関係を挿入することができるからです。ある時点で子供をテーブルから取り出さなければならないので、それは不可能だと思いますか? – mogronalol

+0

あなたはどのRDBMSを使用していますか? –

答えて

1

RDBMSによっては、INSERT/UPDATEトリガーでこれを処理できます。単純に親を子供にもならないように制限するには、あまりにも悪くあってはいけません(私はトリガーを必要以上に使用することは嫌ですが)。特定のレベル数(たとえば100)に制限しようとすると、パフォーマンスの問題が発生する可能性があります。

MS SQL Serverでは、制約でユーザー定義関数を使用することもできます。しかし、限界があるので、私はそれがここで動作するかどうかわからない。私はそれをテストしようとします。

EDIT:

私は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 
関連する問題