在学习触发器之前,先弄清DDL,DML,DQL,DCL的区别:
DDL(Data Definition Language)语句: 数据定义语言,主要是进行定义/改变表的结构、数据类型、表之间的链接等操作。常用的语句关键字有 CREATE、DROP、ALTER 等。
DML(Data Manipulation Language)语句: 数据操纵语言,主要是对数据进行增加、删除、修改操作。常用的语句关键字有 INSERT、UPDATE、DELETE 等。
DQL(Data Query Language)语句:数据查询语言,主要是对数据进行查询操作。常用关键字有 SELECT、FROM、WHERE 等。
DCL(Data Control Language)语句: 数据控制语言,主要是用来设置/更改数据库用户权限。常用关键字有 GRANT、REVOKE 等。
一般人员很少用到DCL语句。
触发器就是当执行某个事件的时候触发另一个事件的执行,根据事件的触发时间可分为
before和after
Before与After区别:before:(insert、update)可以对new进行修改,after不能对new进行修改。两者都不能修改old数据。
但是在sqlserver没有类似Oracle、Postgresql数据库的before功能,这里主要讲after
提要:创建两个表:buy 和detail
create table buy( buyid int not null identity(1,1),-----------表示buyid自增 name varchar(20) not null, cost decimal(8,2) ) create table detail( detailid int not null identity(1,1), buyid int not null, name varchar(20) not null, kind varchar(20) not null, oldcost decimal(8,2) null, newcost decimal(8,2) null, )
关于自增函数和数据类型这里不细讲
注意: 两张虚拟表inserted,deleted
在对表进行操作时,总会产生 INSERTED 和(或)DELETED表,不管这个操作是否已经进行。这里的和/或,要看进行的什么操作,插入,产生 INSERTED 表,删除,产生DELETED表,而UPDATE则两个都会产生。
1.触发器的插入操作:
create trigger tri_buy_insert on buy after insert as insert into detail(buyid,name,kind,oldcost,newcost) select inserted.buyid,inserted.name,'新增',0.0,inserted.cost from inserted,buy where inserted.buyid=buy.buyid
在buy表中插入数据之前,两张表都为空
在buy表中插入一个数据之后:
insert into buy values('薯片',7.50)
不能写为
insert into buy values(1,'薯片',7.50)
否则会报:
仅当使用了列列表并且 IDENTITY INSERT 为 ON 时,才能为表'buy'中的标识列指定显式值。
第一个字段是自增的,插入时不需要赋值
插入后,则会看到:
2.触发器的更新操作:
1.
create trigger tri_buy_update on buy after update as insert into detail(buyid,name,kind,oldcost,newcost) select inserted.buyid,inserted.name,'更新',deleted.cost,inserted.cost from inserted,deleted,buy where inserted.buyid=buy.buyid and deleted.buyid=buy.buyid
此时再更新一下buy表:
update buy set cost=6.7 where name='薯片'
得到效果如下:
若一定要更新第一条数据,可以用instead of
instead of触发器是在insert、update、delete这些操作进行之前就被激活了,并且不再去执行原来的dml SQL操作,而是用触发器内部的SQL语句代替执行。
所以用了instead of的表做任何dml操作,都只会执行触发器内部的语句,INSTEAD OF 触发器的主要优点是使不可被修改的视图能够支持修改。
但其缺点也很明显:
一个table或者view只能有一个instead of
原始dml语句还是不会执行
after触发器和instead of触发器的区别:
after触发器是在操作成功后,所采取的一些动作
而对于instead of触发器,对数据库的操作只是一个“导火线”而已,真正起作用的是触发器里面的动作;往往触发器中会有很多分支判断语句在里面,根据不用的条件做不同的动作。
例如:
创建cart表:
create table cart( cartid int IDENTITY(1,1), name varchar(20) not null, price decimal(8,2) not null, num int not null, total decimal(8,2) default 0.0 )
1.如果消费多于100,就-20
create trigger tri_buy on cart instead of insert as if((select (num*price) from inserted)<100) begin insert into cart(name,price,num,total) select name,price,num,(price*num) from inserted end else begin insert into cart(name,price,num,total) select name,price,num,(price*num-20) from inserted end
插入数据之前,表是空的
insert into cart(name,price,num)values('两个鸡蛋煎饼',17,3)
结果:
再插入一条数据:
insert into cart(name,price,num)values('韩式时尚情侣手链',35,4)
结果:原本是140,最后结果为120
在进行第二题的编写之前要先'drop trigger tri_buy',否则会影响第二题的trigger的使用
drop trigger tri_buy
2.若买的件数小于3不优惠,大于3件,打88折,大于5件,打75折
create trigger tri_buytwo on cart instead of insert as if((select num from inserted)<5 and (select num from inserted)>=3) begin insert into cart(name,price,num,total) select name,price,num,(price*num*0.88) from inserted end else if((select num from inserted)>=5) begin insert into cart(name,price,num,total) select name,price,num,(price*num*0.75) from inserted end else insert into cart(name,price,num,total) select name,price,num,(price*num) from inserted
得到结果:
触发器的删除操作:
create trigger tri_buy_delete on buy instead of delete as insert into detail(buyid,name,kind,oldcost,newcost) select deleted.buyid,deleted.name,'删除',deleted.cost,0.00 from deleted,buy where deleted.buyid=buy.buyid
执行删除操作
delete from buy where name='薯片'
得到结果:
更新进阶:
2.
加入一张新表:calc,如下图:
create table calc( maxcost decimal(8,2) null, mincost decimal(8,2) null, totalcost decimal(8,2) null, avgcost decimal(8,2) null )
刚开始表为:
实现:若calc为空,则插入新数据,若calc表不为空,则更新数据: create trigger tri_buy_insert1 on buy after insert as if not exists(select * from calc) begin insert into calc(maxcost,mincost,totalcost,avgcost) select max(cost),min(cost),sum(cost),avg(cost) from cys_351_buy end else begin update calc set maxcost=(select max(cost) from buy), mincost=(select min(cost) from buy), totalcost=(select sum(cost) from buy), avgcost=(select avg(cost) from buy) end
第一次插入数据结果呈现:
再次插入一个数据:
insert into buy values('冰淇淋',5.5)
得到结果:
对于trigger before的替代方案:
还在学习阶段,学习到新知识会不断补充