09-17:触发器
2018-09-17 本文已影响0人
神坛下的我
- 触发器,存储过程,自定义函数,事务,自动备份
- 数据库完整性
- 主键约束 primary key
实体完整性(唯一约束+非空约束),对象具有和同类对象区别唯一的特征
(字段)。 - 外键约束 foreign key
引用完整性 一个对象需要引用的对象存在来证明正确性。 - 检查约束 check
域完整性 例如:身高在范围的约束内,性别在列表in的约束内,电话在like
约束内;规则rule - 自定义完整性
触发器(sqlserver)
- 满足条件,触发操作
- DDL触发器
insert,delete,update
;DDL触发器建立在表和视图上,一个表(视图)可以建立多
个触发器。 - DDL触发器分为后触发器和替代触发器。
- 触发器有两张伪表:
inserted表和deleted表。
- create/alter/drop trigger trg_Xxx
- eg:申请新生入住寝室,需要判断入住的寝室是否已经满员,如果满员拒绝入住。
基本语法1:
create trigger trg_admin
on admin
for insert
as
begin
print '有插入发生'
end
基本语法2:
alter trigger trg_admin
on admin
for insert
as
begin
declare @countno int
select @countno = count(*) from admin
if @countno <= 4
begin
print '有插入发生'
end
else
begin
-- 报错信息 参数1消息,参数2级别,参数3自编号
raiserror('对不起,已经满员',16,10)
-- 回滚操作
rollback transaction
end
end
insert into admin values('0005','123','aaa',1)
解题:
create trigger trg_changeroom_student
on student
for insert
as
begin
declare @name varchar(20),@newroomno char(4),@countno int,@str varchar(100)
-- 获取到该学生希望入住的寝室
select @name=name,@newroomno = bedno from inserted
select @countno = count(*) from student
where substring(bedno,1,4) = @newroomno
-- 判断该学生入住后,寝室是否超员
if @countno > 4
begin
set @str='您要入住的寝室'+@newroomno+'已经满员'
raiserror(@str,16,20)
rollback transaction
end
else
begin
print '欢迎'+@name+'同学入住'+@newroomno+'寝室'
end
end
insert into student(sno,name,sex,high,birthday,jointime,homephone,bedno,address,avgscore,area,cno,imgsrc,pwd)
values ('16010102','张三','女',172,'1989-03-01 00:00:00','2009-09-01 00:00:00','13931111112','0301','嘉陵区',73.3,'南充','090101','','123')
select * from studnt
-- 进阶上题
1.解决插入寝室是否满员
2.插入的寝室可以入住,编床位号的问题
3.插入寝室可以入住,找空床
create trigger trg_changeroom_student
on student
for insert,update
as
begin
declare @insertno int,@deleteno int
declare @name varchar(20),@sno char(8),
@newroomno char(4),@countno int,@str varchar(100),@oldroomno char(6)
select @insertno = count(*) from inserted
select @deleteno = count(*) from deleted
-- 如果插入临时表(幻表)数量 > 0 同时 删除幻表 数量 > 大于0 说明这是修改
-- 获取到该学生希望入住的寝室
select @sno=sno,@name=name,@newroomno = bedno from inserted
select @countno = count(*) from student
where substring(bedno,1,4) = @newroomno
-- 判断该学生入住后,寝室是否超员
if @countno > 4
begin
set @str = '您要入住的寝室'+@newroomno + '已经满员'
raiserror(@str,16,20)
-- 对于成功入住 插入和修改逻辑一样
if(@deleteno > 0 and @insertno > 0)
begin -- 修改的拒绝处理
select @sno=sno,@name=name,@newroomno = bedno from inserted
select @oldroomno = bedno from deleted
print @oldroomno
update student
set bedno = @oldroomno
where sno = @sno
print @name + '同学被退回' +@oldroomno + '寝室'
end
else -- 插入的拒绝处理
begin
rollback transaction
end
end
else
begin
declare @j int = 1,@temproomno char(4) = @newroomno,@tempbedno char(6)
while @j <=4 -- 循环产生本寝室合理的床位号,查找该床位是否被使用,
--如果没有被使用,退出循环
begin
set @tempbedno = @newroomno + '0' + convert(char(1),@j)
if not exists(select bedno from student
where bedno = @tempbedno)
begin
print @tempbedno
update student
set bedno = @tempbedno
where sno = @sno
break
end
set @j = @j + 1
end
print '欢迎' + @name + '同学入住' + @newroomno +'寝室'
end
end
insert into student(sno,name,sex,high,birthday,jointime,homephone,bedno,address,avgscore,area,cno,imgsrc,pwd)
values ('16010108','张三','女',172,'1989-03-01 00:00:00','2009-09-01 00:00:00','13931111112','0401','嘉陵区',73.3,'南充','090101','','123')
delete from student
where sno = '16010103'
update student
set bedno = '0301'
where sno = '16010108'
select * from student
步骤:
-- 1.通过幻表找出新的寝室
-- 2.统计新寝室的人数是否超员
-- 3.如果超员
-- 3.1 判断是 插入引发触发,报异常回滚
-- 3.2 修改引入触发 ,报异常 找到原来的寝室号 修改回原寝室(也可以通过回滚取消更新来做,如果不允许直接回床位
-- 只能在原寝室重新分配)
-- 4.不超员 欢迎入住,并计算出床位号
- 找出030101到030104没有人住的床位
1.创建临时表,查询空床
create table tempbedno
(
tempbedno char(8)
)
declare @i int = 1
while(@i <= 4)
begin
insert into tempbedno values('0301'+'0'+convert(char(1),i))
set @i = @i + 1
end
select * from tempbedno where tempbedno not in(
select bedno from student
where substring(bedno,1,4) = '0301'
)
drop table tempbedno
2.循环查询空床
declare @j int = 1,@temproomno char(6) = '0301',@tempbedno char(6)
while @j <= 4
begin
set @tempbedno = '0301'+'0'+convert(char(1),@j)
if not exists(select bedno from student
where bedno = @tempbedno)
begin
print @tempbedno
break
end
set @j = @j+1
end
- DCL触发器