我正在研究触发器和约束。
我有一个使用触发器的问题(说实话,我不确定如何使用触发器。)
假设我们有一个教师表。
这个教师表包含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
和
假设学生人数上限为25(学生人数上限由老师定义,因此可以是10、22、25 …等任意数字)
一个学生想添加鲍勃的班级。但是,我想触发拒绝添加学生的触发器。(因为鲍勃的班级已满。)
但是,我不确定如何创建触发器.. :( ..(这是第一次研究触发器…。)
任何人都可以帮助创建示例代码来理解触发器部分吗?
首先,我认为这是一条数据规则,因此应集中实施。也就是说,应该由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
概念表来限制查询的范围以及何时触发查询。您还需要确保事务正确序列化,以防止并发问题。尽管涉及到,但并不复杂。
我强烈推荐《面向数据库专业人员的应用数学》一书,作者是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)
);
然后添加一些“帮助”存储的过程/函数以保持更新顺序。
SQL Server触发器是特殊的存储过程,它们会自动执行以响应数据库对象,数据库和服务器事件。 SQL Server提供三种类型的触发器: 数据操作语言(DML)触发器,它们响应针对表的INSERT,UPDATE和DELETE事件而自动调用。 数据定义语言(DDL)触发器响应CREATE,和DROP语句而触发。 DDL触发器也会响应执行类似操作的某些系统存储过程而触发。 登录触发器以响应事件而触
主要内容:创建触发器,示例在本章中,我们将讨论和学习PL/SQL中的触发器。 触发器是存储的程序,在发生某些事件时会自动执行或触发。事实上,触发器是为了响应以下任何事件而被执行的 - 数据库操作(DML)语句(,或) 数据库定义(DDL)语句(,或)。 数据库操作(,,,或)。 可以在事件关联的表,视图,模式或数据库上定义触发器。 使用触发器的好处 触发器可以用于以下目的 - 自动生成一些派生列值 强化参照完整性 事件记录
问题内容: 我有一些代码需要调试帮助,但我认为,如果我能运行其中之一,我将可以得到其余的代码(哦,我希望如此)。 我正在尝试通过sqlplus在我学校的服务器上运行的表上执行此操作,如果有帮助的话。 问题答案: 遇到错误时,指定什么错误总是有帮助的。触发器中的调用中存在语法错误。该过程需要两个参数,一个数字和一个字符串。您传入的是一个长字符串的单个参数。 假设您的表格中有一列,则该值应有效。
问题内容: 我有一个表orderDetails,其中包含订单的产品 productId color size quantity 和一桌股票 productId size color stock 订单完成后,我将使用此查询在表格中插入商品 然后我在表上有一个触发器: 通过此触发器,我想减少库存,但是只有第一个产品受到影响,其他数量保持不变。 我想念什么? 谢谢你。 问题答案: 要点是:您假设将为插入
问题内容: 我在使用JPA / Hibernate(3.5.3)设置时遇到麻烦,在这里我有一个实体,即“ Account”类,该类具有子实体列表,“ Contact”实例。我试图能够将Contact的实例添加/删除到Account的List 属性中。 将新实例添加到集合中并调用saveOrUpdate(account)可以保留所有可爱的东西。如果我然后选择从列表中删除该联系人并再次调用saveOr
问题内容: 在MSSQL中执行TRUNCATE(而不是删除)时,如何触发触发器 问题答案: 来自msdn: TRUNCATE TABLE无法激活触发器,因为该操作不会记录单个行的删除。