まず、私は、これはデータ・ルールであるため、一元的に実施されるべきだと思う)....トリガーについて勉強するのは初めてです。つまり、すべてのアプリケーションが不正なデータを書き込むのを防ぐDBMSによって(各アプリケーションの個々のコーダに悪いデータを書き込まないようにする)DBの制約が適用されます。
第2に、AFTER
トリガーが適切だと思う(INSTEAD OF
トリガーではなく)。
第3に、これは外部キーと行レベルCHECK
の制約を使用して強制できます。
制約タイプのトリガーでは、一般に、トリガーテストでは、この結果が空であることを示すために、不良データを返すクエリを記述します。
私は推測するように、テーブルの詳細を多く投稿していません。私はstudent_number
と書いてあります。それは私が名前を変更し、学生のための識別子を仮定しますので、それは識別子のような音であるとしてstudent_id
次のとおりです。
SQL Serverでの
WITH EnrolmentTallies
AS
(
SELECT teacher_id, COUNT(*) AS students_tally
FROM Enrolment
GROUP
BY teacher_id
)
SELECT *
FROM Teachers AS T
INNER JOIN EnrolmentTallies AS E
ON T.teacher_id = E.teacher_id
AND E.students_tally > T.students_tally;
、トリガ定義は、次のようになります
CREATE TRIGGER student_tally_too_high ON Enrolment
AFTER INSERT, UPDATE
AS
IF EXISTS (
SELECT *
FROM Teachers AS T
INNER JOIN (
SELECT teacher_id, COUNT(*) AS students_tally
FROM Enrolment
GROUP
BY teacher_id
) AS E
ON T.teacher_id = E.teacher_id
AND E.students_tally > T.students_tally
)
BEGIN
RAISERROR ('A teachers''s student tally is too high to accept new students.', 16, 1);
ROLLBACK TRANSACTION;
RETURN
END;
しかし、いくつかの考慮事項があります。テーブルへのUPDATE
ごとにこのようなクエリを実行すると、非常に効率が悪くなる可能性があります。 UPDATE()
(または列の順序が頼りになると思われる場合はCOLUMNS_UPDATED
)および/またはdeleted
およびinserted
の概念表を使用して、クエリの範囲と発生する時間を制限する必要があります。並行性の問題を防ぐために、トランザクションが適切にシリアル化されていることを確認する必要もあります。関与していますが、それはひどく複雑ではありません。
Applied Mathematics for Database Professionals By Lex de Haan, Toon Koppelaarsの第11章(コード例はOracleですが、SQL Serverに簡単に移植することができます)を強くお勧めします。
トリガーなしで同じことを達成することは可能かもしれません。この考えは(teacher_id, students_tally)
のスーパーキーをEnrollmentで参照させることです。そのために、シーケンスが最大の集計を決して超えないというテストでユニークな生徒の出現が維持されます。
ここではいくつかの裸の骨のSQLのDDLです:
CREATE TABLE Students
(
student_id INTEGER NOT NULL,
UNIQUE (student_id)
);
CREATE TABLE Teachers
(
teacher_id INTEGER NOT NULL,
students_tally INTEGER NOT NULL CHECK (students_tally > 0),
UNIQUE (teacher_id),
UNIQUE (teacher_id, students_tally)
);
CREATE TABLE Enrolment
(
teacher_id INTEGER NOT NULL UNIQUE,
students_tally INTEGER NOT NULL CHECK (students_tally > 0),
FOREIGN KEY (teacher_id, students_tally)
REFERENCES Teachers (teacher_id, students_tally)
ON DELETE CASCADE
ON UPDATE CASCADE,
student_id INTEGER NOT NULL UNIQUE
REFERENCES Students (student_id),
student_teacher_sequence INTEGER NOT NULL
CHECK (student_teacher_sequence BETWEEN 1 AND students_tally)
UNIQUE (teacher_id, student_id),
UNIQUE (teacher_id, student_id, student_teacher_sequence)
);
その後の更新にシーケンスを維持するために、いくつかの「ヘルプ」保存されprocsの/機能を追加します。
トリガーはデータベース固有の傾向があるため、興味のあるデータベースを追加する必要があります。 –
ようこそStackOverflow:コード、XML、またはデータサンプルを投稿する場合は、テキストエディタでこれらの行を強調表示し、エディタツールバーの "コードサンプル"ボタン( '{}')をクリックしてください。それを強調する構文! 'orgiesと'
'タグは本当に必要ありません。 –
これはビジネスルールです。これは、データベースのトリガーや制約としてではなく、アプリケーションソフトウェアで実装すると予想されます。データベースの制約とトリガーは、一般に参照整合性を強制します(つまり、内部的にデータの一貫性を維持します)。クラスが25を超えないようにするためのバックストップになるかもしれませんが、アプリはまず最初にその試みを止めるべきです。 –