Dc *_*ing 5 sql triggers constraints
我正在研究触发器和约束.
我有一个问题要使用触发器(说实话,我不确定如何使用触发器..)
假设我们有一个教师表.
这个教师表包含teacher_id,ssn,first_name,last_name,class_time
例如,
|teacher_id|ssn | first_name | last_name | student_number| max_student
|1 |1234 | bob | Smith | 25 |25
|2 |1235 | kim | Johnson | 24 |21
|3 |1236 | kally | Jones | 23 |22
Run Code Online (Sandbox Code Playgroud)
和
假设学生编号的最大数量为25(学生的最大数量将由教师定义,因此它可以是任何数字,如10,22,25 ...)
并且学生想要添加鲍勃的课程.但是,我想制作拒绝添加学生的触发器.(因为bob的类已经满了..)
但是,我不太确定创建触发器的方式.. :( ..(这是第一次研究触发器......)
任何人都可以帮助创建示例代码来理解触发器部分吗?
one*_*hen 10
首先,我认为这是一个数据规则,因此应该集中实施.也就是说,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;
Run Code Online (Sandbox Code Playgroud)
在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;
Run Code Online (Sandbox Code Playgroud)
然而,还有一些进一步的考虑因素.在每个UPDATE表之后执行这样的查询可能是非常低效的.您应该使用UPDATE()(或者COLUMNS_UPDATED,如果你认为列顺序可依靠)和/或deleted与inserted概念表来限制查询的范围,当它是火.您还需要确保正确地序列化事务以防止并发问题.虽然参与其中,但并不是非常复杂.
我强烈推荐" 数学专业人员应用数学 "一书作者:Lex de Haan,Toon Koppelaars,第11章(代码示例是Oracle,但可以轻松移植到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)
);
Run Code Online (Sandbox Code Playgroud)
然后添加一些'help'存储过程/函数来维护更新时的序列.
| 归档时间: |
|
| 查看次数: |
15080 次 |
| 最近记录: |