数据库sqlserver-----触发器的插入,更新和删除
提要:创建两个表:buy 和detail想了解更多:自增函数:http://t.csdn.cn/u1VAX数据类型:http://t.csdn.cn/AVGMk 两张虚拟表inserted,deleted在buy表中插入数据之前,两张表都为空在buy表中插入一个数据之后:不能写为否则会报:仅当使用了列列表并且 IDENTITY INSERT 为 ON 时,才能为表'buy'中的标识列指定显式值。第
在学习触发器之前,先弄清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的替代方案:
还在学习阶段,学习到新知识会不断补充
更多推荐
所有评论(0)