1

親と子の 2 つのテーブルがあるとします。親には MaxChildren (int) フィールドがあり、子には親レコードにリンクする Enabled (ビット) フィールドと ParentID (int) フィールドがあります。

Enabled = 1 の親ごとに MaxChildren を超えるレコードが存在できないような制約を設定したいと思います。これは、Child テーブル内のレコードを挿入または更新しようとすると、該当する MaxChildren の値、または該当する子レコードの現在の数よりも MaxChildren を下げようとする試みは失敗します。

私は MS SQL Server を使用していますが、標準的な SQL の方法があることを願っています。

4

1 に答える 1

4

これは標準の SQL-92 エントリ レベルの構文です。つまり、SQL 製品で広く実装されている外部キーや行レベルのCHECK制約などの「バニラ」構文を使用します (特に mySQL ではありません)。

CREATE TABLE Parent
(
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL
    CHECK (MaxChildren > 0), 
 UNIQUE (ParentID),
 UNIQUE (ParentID, MaxChildren)
);

CREATE TABLE Child
(
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL, 
 FOREIGN KEY (ParentID, MaxChildren)
    REFERENCES Parent (ParentID, MaxChildren)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 OccurrenceNumber INTEGER NOT NULL, 
 CHECK (OccurrenceNumber BETWEEN 1 AND MaxChildren), 
 UNIQUE (ParentID, OccurrenceNumber)
);

ビット フラグ列の使用は避けることをお勧めします。むしろ、制限のない 2 番目のテーブルをMaxChildren作成し、行が表示されるテーブルに基づいて Enabled 列を暗示することができます。これをモデル化するには、おそらく 3 つのテーブルが必要になるでしょう: Enabled のサブタイプ テーブルを持つすべての子のスーパータイプ テーブル。VIEW次に、暗黙の Enabled 列を使用しUNIONて 2 つのサブタイプを作成できます。

CREATE TABLE Parents
(
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL
    CHECK (MaxChildren > 0), 
 UNIQUE (ParentID),
 UNIQUE (ParentID, MaxChildren)
);

CREATE TABLE Children
(
 ChildID INTEGER NOT NULL, 
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL, 
 FOREIGN KEY (ParentID, MaxChildren)
    REFERENCES Parents (ParentID, MaxChildren)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 UNIQUE (ChildID), 
 UNIQUE (ChildID, MaxChildren),  
);

CREATE TABLE EnabledChildren
(
 ChildID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL, 
 FOREIGN KEY (ChildID, MaxChildren)
    REFERENCES Children (ChildID, MaxChildren)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 OccurrenceNumber INTEGER NOT NULL, 
 CHECK (OccurrenceNumber BETWEEN 1 AND MaxChildren), 
 UNIQUE (ChildID)
);

CREATE VIEW AllChildren
AS
SELECT ChildID, 1 AS ENABLED
  FROM EnabledChildren
UNION
SELECT ChildID, 0 AS ENABLED
  FROM Children
EXCEPT
SELECT ChildID, 0 AS ENABLED
  FROM EnabledChildren;
于 2011-11-25T11:45:25.810 に答える