首先,我認爲這是一個數據規則,因此應該集中執行。也就是說,應該有一個由DBMS強制執行的數據庫約束(或等效),以防止所有應用程序寫入錯誤的數據(而不是依靠每個應用程序的單個編碼器來避免寫入錯誤的數據)
其次,我認爲一個AFTER
觸發器是合適的(而不是INSTEAD OF
觸發)。
第三,這可以通過使用外鍵和行級CHECK
約束強制執行。
對於約束類型觸發器,這個想法一般是寫一個查詢,然後返回壞數據的觸發測試,這一結果是空的。
你還沒有發佈表格的很多細節,所以我會猜測。我認爲student_number
是爲了學生的理想;因爲這是它聽起來像一個標識符,我改個名字,並承擔學生的標識是student_id
:
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;
在SQL Server中,觸發定義會是這個樣子:
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章(代碼示例是甲骨文,但可以很容易地移植到SQL Server)。
不用觸發器就可以達到同樣的效果。這個想法是在登記中引用(teacher_id, students_tally)
的超級密鑰,對於這個唯一的學生事件序列將通過測試保持序列永遠不會超過最大計數。
下面是一些裸露的骨頭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)
);
然後添加存儲的特效/功能上保持更新序列一些「幫助」。
您必須添加您感興趣的數據庫,因爲觸發器往往是數據庫特定的。 – 2012-03-12 07:40:36
歡迎使用StackOverflow:如果您發佈代碼,XML或數據樣本,請**在文本編輯器中突出顯示這些行,然後單擊編輯器工具欄上的「代碼示例」按鈕(「{}」)以精確地格式化和語法突出它!不需要雜亂的' 'orgies和'
'標籤,真的...... – 2012-03-12 07:46:07
這是一個業務規則,我希望這可以在您的應用程序軟件中實現,而不是作爲數據庫中的觸發器或約束。數據庫約束和觸發器通常強制引用完整性(也就是說,它們保持內部數據一致),雖然它可能是確保類不超過25的支持者,但應用程序應該真正停止嘗試。 – 2012-03-12 08:12:42