示例:创建级联触发器。例,若修改表[A]的name,则级联也更新修改表[B]的name。
create trigger tri_update_A
on A
for update
as
declare @OLDname char(10),@NEWname char(10)
select @OLDname=deleted.name , @NEWname=inserted.name
from deleted,inserted
where deleted.id=inserted.id
print '准备级联更新B表中的name信息'
update B
set name=@NEWname
where name=@OLDname
用触发器来实现级联更新级联删除
(参考范本)触发器方式:
createtrigger trg_A
on A
for update,delete
as
begin
if exists(select 1 from inserted)
update
B set Name=(select Name from inserted)
where Name=(select Name from deleted)
else
delete B where Name=(select Name from deleted)
end
go
应用示例:
/*用触发器来实现级联更新级联删除*/
--先创建数据库[教学管理]及学生表、课程表、成绩表
CREATE DATABASE [教学管理]
GO
USE [教学管理]
GO
CREATE TABLE [dbo].[学生表](
[学号] [nvarchar](50) primary key NOT NULL,
[姓名] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
)
CREATE TABLE [dbo].[课程表](
[课程号] [nvarchar](50) primary key NOT NULL,
[课程名称] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
)
CREATE TABLE [dbo].[成绩表](
[学号] [nvarchar](50) NOT NULL ,
[课程号] [nvarchar](50) NOT NULL ,
[成绩] [nvarchar](50) NULL,
primary key(学号,课程号),
)
--删除表:
--drop table 学生表;
--drop table 课程表;
--droptable 成绩表;
insert into 学生表 values('001','张三');
insert into 学生表 values('002','李四');
insert into 学生表 values('003','王五');
insert into 课程表 values('101','语文');
insert into 课程表 values('102','数学');
insert into 课程表 values('103','电脑');
insert into 成绩表 values('001','101','82');
insert into 成绩表 values('001','102','56');
insert into 成绩表 values('002','101','83');
insert into 成绩表 values('002','102','77');
insert into 成绩表 values('003','103','83');
insert into 成绩表 values('003','102','93');
--创建一个触发器来实现级联更新、级联删除;
create trigger trg_A
on 学生表
for update,delete
as
begin
if exists(select 1 from inserted)
update 成绩表 set 学号=(select 学号 from inserted)
where 学号=(select 学号 from deleted)
else
delete 成绩表 where 学号=(select 学号 from deleted)
end
go
--删除操作,下面删除命令,将学号为001的学生信息在学生表删除,由于已建立级联触发器,成绩表的相关信息也自动被删除:
delete from 学生表 where 学号='001'
select * from 学生表 order by 学号;
select * from 成绩表 order by 学号, 课程号;
--更新操作,将原学号为003的学生信息在学生表更新为201903,由于已建立级联触发器,成绩表的相关信息也自动被更新:
update 学生表 set 学号='201903' where 学号='003'
select * from 学生表 order by 学号
select * from 成绩表 order by 学号, 课程号
分析问题并解决问题:
--更新[课程表]操作,由于[课程表]没有建立级联触发器,成绩表的相关信息没有被更新:
update 课程表 set 课程号='1103' where 课程号='103'
--查询:
select * from 学生表 order by 学号
select * from 课程表 order by 课程号
select * from 成绩表 order by 学号, 课程号
练一练:参考上面示例trg_A,请创建课程表与成绩表的级联更新、级联删除触发器。
--创建一个触发器来实现[课程表]与[成绩表]级联更新级联更新、删除
(参考解答)
create trigger trg_B
on 课程表
for update,delete
as
begin
if exists(select 1 from inserted)
update 成绩表 set 课程号=(select 课程号 from inserted)
where 课程号=(select 课程号 from deleted)
else
delete 成绩表 where 课程号=(select 课程号 from deleted)
end
go
update 课程表 set 课程号='1102' where 课程号='102'
select * from 学生表 order by 学号
select * from 课程表 order by 课程号
select * from 成绩表 order by 学号, 课程号
练习:请删除课程表某门课试试,观察情况
(2)创建DDL触发器
语法格式如下:
CREATE TRIGGER trigger_name
ON { ALL SERVER | DATABASE }
[ WITH <ddl_trigger_option> [ ,...n ] ]
{ FOR | AFTER } { event_type | event_group } [ ,...n ]
AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME < method specifier > [ ; ] }
参数说明如下:
DATABASE:将DDL触发器的作用域应用于当前数据库。如果指定了此参数,则只要当前数据库中出现event_type或event_group,就会激发该触发器。
ALL SERVER:将 DDL 或登录触发器的作用域应用于当前服务器。如果指定了此参数,则只要当前服务器中的任何位置上出现 event_type 或 event_group,就会激发该触发器。
event_type:执行之后将导致激发DDL触发器的T-SQL语句事件的名称,只不过在名称上与T-SQL 语句略有不同,比如CREATE TABLE语句对应的事件名称为CREATE_TABLE,在关键词之间加上了下划线,常见的选项有CREATE_TABLE、ALTER_TABLE、DROP_TABLE、CREATE_VIEW等。
event_group:预定义的T-SQL语言事件分组的名称。执行任何属于event_group 的Transact-SQL语言事件之后,都将激发DDL触发器。DDL事件组中列出了DDL触发器的有效事件组。CREATE TRIGGER运行完毕之后,event_group 还可通过将其涵盖的事件类型添加到sys.trigger_events目录视图中来作为宏使用。
【例】创建学生成绩管理系统数据库作用域的DDL触发器。对“学生成绩管理系统”的[教务数据库],当试图删除一个表时,阻止并撤销删除表的操作。
本例代码如下:
USE [教务数据库]
GO
CREATE TRIGGER PreventDropTable
ON DATABASE
AFTER DROP_TABLE
AS
BEGIN
PRINT '不能删除表'
ROLLBACK TRANSACTION
END
【例】创建服务器作用域的DDL触发器。当试图删除一个数据库时,阻止并撤销删除数据库的操作。
对“学生成绩管理系统”的[教务数据库],
本例代码如下:
USE [教务数据库]
GO
CREATE TRIGGER PreventDropDatabase
ON ALL SERVER
AFTER DROP_DATABASE
AS
BEGIN
PRINT ‘不能删除该数据库’
ROLLBACK TRANSACTION
END