数据库(触发器、数据库事务、存储练习)
触发器:
触发器为特殊类型的存储过程,可在执行语言事件时自动生效。SQL Server 包括三种常规类型的触发器:DML 触发器、DDL 触发器和登录触发器。
当服务器或数据库中发生数据定义语言 (DDL) 事件时将调用 DDL 触发器。登录触发器将为响应 LOGON 事件而激发存储过程。与 SQL Server 实例建立用户会话时将引发此事件。
当数据库中发生数据操作语言 (DML) 事件时将调用 DML 触发器。DML 事件包括在指定表或视图中修改数据的 INSERT 语句、UPDATE 语句或 DELETE 语句。DML 触发器可以查询其他表,还可以包含复杂的 Transact-SQL 语句。将触发器和触发它的语句作为可在触发器内回滚的单个事务对待。如果检测到错误(例如,磁盘空间不足),则整个事务即自动回滚。
主要讲述DML触发器,DML触发器有两种:AFTER(FOR),INSTEAD OF触发器,同时DML 触发器使用 deleted 和 inserted 逻辑(概念)表。 它们在结构上类似于定义了触发器的表,即对其尝试执行了用户操作的表。 在 deleted 和 inserted 表保存了可能会被用户更改的行的旧值或新值。
- 对于INSERT 操作,inserted保留新增的记录,deleted无记录
- 对于DELETE 操作,inserted无记录,deleted保留被删除的记录
- 对于UPDATE操作,inserted保留修改后的记录,deleted保留修改前的记录
示例一:DELETE触发器的创建和执行,用的Instead Of
示例二:执行删除一条数据,用deleted来表示被删除的那条数据,从中获取
示例三:insert添加一条数据,inserted表示新添加的数据,从中获取教师编号,并且根据教师编号来查看是男是女,调换男女。
数据库事务:
数据库事务(Database Transaction) 是指作为单个逻辑工作单元执行的一系列操作。
事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。
设想网上购物的一次交易,其付款过程至少包括以下几步数据库操作:
更新客户所购商品的库存信息
保存客户付款信息--可能包括与银行系统的交互
生成订单并且保存到数据库中 · 更新用户相关信息,例如购物数量等等 正常的情况下,这些操作将顺利进行,最终交易成功,与交易相关的所有数据库信息也成功地更新。但是,如果在这一系列过程中任何一个环节出了差错,例如在更新商品库存信息时发生异常、该顾客银行帐户存款不足等,都将导致交易失败。一旦交易失败,数据库中所有信息都必须保持交易前的状态不变,比如最后一步更新用户信息时失败而导致交易失败,那么必须保证这笔失败的交易不影响数据库的状态--库存信息没有被更新、用户也没有付款,订单也没有生成。否则,数据库的信息将会一片混乱而不可预测。
数据库事务正是用来保证这种情况下交易的平稳性和可预测性的技术。
begin tran (或transaction) --开始事务
commit --提交事务
rollback --回滚事务
事务特性:
A原子性(atomicity)
C一致性(consistency)
I隔离性(isolation)
D持久性(durability)
@@ERROR 是判断事务有没有错的条件,无错时值为0,有错时值不为0。
select * from cangku
begin tran --开始事务
insert into cangku values(10008,'Boxster',70,10,1004)--没有错
if @@ERROR >0
begin--每一个执行语句后面写这句话是为了如果上一句有错误,
--下面不管有多少执行语句,都不会执行,直接到tranrollback
goto tranrollback--到最后一个执行语句的tranrollback
end
insert into cangku values(10002,'极光',66.50,10,1002)--主键约束
if @@ERROR>0
goto tranrollback
insert into cangku values(10009,'XF',40,10,1003)--没有错
if @@ERROR>0
begin
tranrollback: --需要加上冒号
rollback tran --回滚所有事务中执行过的命令(撤销所有执行语句)
end
else
begin
commit tran --提交事务(只有真正的走到了commit才是真正的更改数据库的数据)
end
练习:创建三个表并写一个简单的存储过程,要求可以进货、出货并打印小票。
在没有此货物并且为进货时,添加上这一行信息;
在没有此货物并且为出货时,打印没有此货物!
use lianxi go create table gong ( gcode int primary key, --供应商编号 gname varchar(20), --供应商名称 gtel varchar(20) --供应商电话 ) go create table cang ( code int primary key , -- 货品编号 cname varchar(20), --货品名称 cshu int, --货品数量 cprice decimal(18,2), --货品价格 cg int, --货品供应商编号 ) go create table men ( mcode int identity(1000001,1), --货品编号 mname varchar(20), --货品名称 mshu int, --货品数量 mprice decimal(18,2), -- 货品价格 mzong decimal(18,2) ) go insert into gong values (1001, '天启电器','13452236789') insert into gong values (1002, 'Davy家具','17552223761') insert into gong values (1003, '夏华电商','17232235521') insert into gong values (1004, '网易电商','16532238817') select *from gong insert into cang values(231001,'联想 小新Air 13 Pro',20,5499,1001) insert into cang values(231002,'苹果iPad mini2',20,1950,1004) insert into cang values(231003,'沙发',12,2699,1002) insert into cang values(231004,'康佳智能冰箱',10,2699,1003) insert into cang values(231005,'微软 Surface 3',24,3999,1004) insert into cang values(231006,'安吉尔净水器',10,1668,1003) insert into cang values(231007,'康佳电视 LED55UC2',10,4399,1003) insert into cang values(231008,'Littleswan烘干洗衣机',5,2998,1003) insert into cang values(231009,'Dell 灵越 15 5000',20,3999,1001) insert into cang values(231010,'OPPO R9 全网通',14,2499,1004) insert into cang values(231011,'衣柜',12,566,1002) insert into cang values(231012,'小米MAX',15,1600,1004) insert into cang values(231013,'洛基亚N1',30,1199,1004) insert into cang values(231014,'红米手机3S',50,699,1001) insert into cang values(231015,'太阳能',7,1999,1003) insert into cang values(231016,'连体书桌柜',8,1680,1002) insert into cang values(231017,'海信LED55EC760UC',13,4999,1003) insert into cang values(231018,'xbox-one',20,3799,1004) insert into cang values(231019,'华为P9',20,2860,1004) insert into cang values(231020,'客厅成套家具',3,5644,1002) insert into cang values(231021,'索尼相机',9,4599,1004) insert into cang values(231022,'华硕 W519L',17,3500,1001) insert into cang values(231023,'数码摄像机',10,2798,1003) insert into cang values(231024,'三星UA55KS9800',5,18099,1003) insert into cang values(231025,'三星 900X3L',15,8999,1001) insert into cang values(231026,'小米平板2',37,999,1004) select *from cang delete from cang create proc chuchu @code int, @cname varchar(20), --货品名称 @cshu int, --货品数量 @cprice decimal(18,2), --货品价格 @cg int as begin declare @count int select @count=COUNT(*)from cang where code=@code declare @shu int select @shu=cshu from cang where code=@code if @count>0 begin if @cshu>0--进货 update cang set cshu= @shu+@cshu where code=@code if @cshu<0 --出货 begin if @shu+@cshu>=0 update cang set cshu=@shu+@cshu where code=@code declare @scshu int set @scshu=-@cshu declare @zong decimal(18,2) set @zong=@cprice*@scshu insert into men values(@cname,@cprice,@scshu,@zong) if @shu+@cshu<0 print '货物量不足,请及时补充' end end else begin if @cshu>0 insert into cang values (@code,@cname,@cprice,@cshu,@cg) if @cshu<0 print '仓库中无此货物' end end go exec chuchu @code=231001,@cname='联想 小新Air 13 Pro',@cprice=5499,@cshu=15,@cg=1001 exec chuchu @code=231005,@cname='微软 Surface 3',@cprice=3999,@cshu=-10,@cg=1004 exec chuchu @code=231030,@cname='iphone 3s',@cprice=1200,@cshu=10,@cg=1001 exec chuchu @code=231031,@cname='乐视tv',@cprice=1200,@cshu=-10,@cg=1002 select *from cang select *from men