0

次の表があります。

CLASS_HAS_STUDENTS (
    PER_SSN INTEGER NOT NULL,
    PER_YEAR INTEGER NOT NULL, /*These two are PKs for a student*/
    SCHOOL_CODE INTEGER NOT NULL, /*PK for a school*/
    CLASS_YEAR INTEGER NOT NULL,
    CLASS_NUMBER INTEGER NOT NULL,
    CLASS_TEACHTYPE CHAR(3) NOT NULL, /*These three are PKs for a class*/
    STUDCLASS_STATUS CHAR(1) NOT NULL
        constraint CKC_STUDCLASS_STATUS_CLASS_TI check (StudClass_Status IN ('E', 'Y', 'T', 'P', 'F')),
    STUDCLASS_LISTNUMBER INTEGER NOT NULL,
    STUDCLASS_ROLLNUMBER INTEGER NOT NULL
);

(このコードにはいくつかの小さな制約がありません)

ここで、1つのPER_SSN / PER_YEAR(個人のPK)が1つの「E」(「登録済み」)ステータスのみを持つことができることを確認する方法が必要です。トリガーでこれを行うことはできず(同じテーブルから選択している場合)、チェック制約でこれを行うことができるかどうかわかりません(ここでCOUNT()を使用できますか?)。どんな助けでも大歓迎です。

4

3 に答える 3

4

関数ベースの一意のインデックスを作成して、この種のことを強制できます。そのような制約を作成することはできません。

これは、Oracle b-treeインデックスがNULLデータにインデックスを付けないという事実を利用しているため、インデックスには、がである行のエントリのみが含まれstudclass_statusますE

CREATE UNIQUE INDEX idx_one_enrolled
    ON class_has_students( CASE WHEN studclass_status = 'E'
                                THEN per_ssn
                                ELSE null
                            END,
                           CASE WHEN studclass_status = 'E'
                                THEN per_year
                                ELSE null
                            END );
于 2012-07-29T20:50:26.743 に答える
1

私はあなたの質問に少し混乱しています。私はあなたがどちらかをしたいと思っていると思います:

1)生徒ごとに複数のステータスが挿入されないようにします(この場合、トリガーが適切です)

また

2)SELECTステートメントを使用して、すでにテーブルにいる生徒を検索します。この場合、次のようなことを行います。

SELECT PER_SSN, PER_YEAR, STUDCLASS_STATUS, COUNT(*)
FROM   CLASS_HAS_STUDENTS
WHERE  STUDCLASS_STATUS = 'E'
HAVING COUNT(*) > 1
GROUP BY PER_SSN, PER_YEAR, STUDCLASS_STATUS;
于 2012-07-29T20:48:23.737 に答える
1

部分的に一意のインデックスを使用してこれを実行できるはずです。社会保障番号ごとに登録されているクラスが1つだけであることを確認するには、これが機能するはずです。

CREATE UNIQUE INDEX ssn_enrollments ON class_has_students(per_ssn) 
WHERE studclass_status='E';

この機能はすべてのSQL実装でサポートされているわけではありませんが、PostgreSQLは少なくともバージョン8以降サポートされていることに注意してください。

于 2012-07-29T20:48:56.570 に答える