SQL Server:触发器详解

SQL Server:触发器详解

  • 1. 概述
  • 2. 触发器的分类
  • 3. Inserted和Deleted表
  • 4. 触发器的执行过程
  • 5. 创建触发器
  • 6. 修改触发器:
  • 7. 删除触发器:
  • 8. 查看数据库中已有触发器:
  • 9. “Instead of”相关示例:
  • 10. “After”触发器
  • 11. 参考资源

1. 概述

触发器是一种特殊的存储过程,它不能被显式地调用,而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活。 所以触发器可以用来实现对表实施复杂的完整性约束。

2. 触发器的分类

SQL Server2000提供了两种触发器:“Instead of” 和“After” 触发器。

一个表或视图的每一个修改动作(Insert、Update和Delete)都可以有一个“Instead of” 触发器,一个表的每个修改动作都可以有多个“After”触发器。

2.1 “Instead of”触发器

  • “Instead of”触发器在执行真正“插入”之前被执行。除表之外,“Instead of” 触发器也可以用于视图,用来扩展视图可以支持的更新操作。
  • “Instead of”触发器会替代所要执行的SQL语句,言下之意就是所要执行SQL并不会“真正执行”

?

1

2

3

4

5

6

7

8

9

alter trigger trigger_学生_Delete

on 学生

instead of Delete

as

begin

    select 学号, 姓名 from deleted

end

 

delete from 学生 where 学号 = 4

上例中定义了“trigger学生_Delete”触发器,该触发器从“delete”表中打印出所要删除的学生.在执行“delete”操作后,会发现“学号 = 4”的学生并未被删除, 原因在于“trigger学生Delete”替代了所要执行的“delete from 学生 where 学号 = 4”语句,而在“trigger学生_Delete”中并未真正删除学生。

2.2 “After”触发器

  • “After”触发器在Insert、Update或Deleted语句执行之后被触发。“After”触发器只能用于表。
  • “After”触发器主要用于表在修改后(insert、update或delete操作之后),来修改其他表

3. Inserted和Deleted表

SQL Server为每个触发器都创建了两个专用表:Inserted表和Deleted表。

  • 这两个表由系统来维护,它们存在于内存中而不是在数据库中,可以理解为一个虚拟的表。
  • 这两个表的结构总是与被该触发器作用的表的结构相同。
  • 触发器执行完成后,与该触发器相关的这两个表也被删除。
  • Deleted表存放由于执行Delete或Update语句而要从表中删除的所有行。
  • Inserted表存放由于执行Insert或Update语句而要向表中插入的所有行。
对表的操作Inserted逻辑表Deleted逻辑表
增加记录(insert)存放增加的记录
删除记录(delete)存放被删除的记录
修改记录(update)存放更新后的记录存放更新前的记录

4. 触发器的执行过程

  • 如果一个Insert﹑update或者delete语句违反了约束,那么这条SQL语句就没有执行成功,因此“After”触发器也不会被激活。

  • “Instead of” 触发器可以取代激发它的操作来执行。它在Inserted表和Deleted表刚刚建立,其它任何操作还没有发生时被执行。因为“Instead of” 触发器在约束之前执行,所以它可以对约束进行一些预处理。

5. 创建触发器

?

1

2

3

4

create trigger trigger_name

on  {table_name|view_name}

{After|Instead of} {insert|update|delete}

as 相应T-SQL语句

6. 修改触发器:

?

1

2

3

4

alter trigger trigger_name

on  {table_name|view_name}

{After|Instead of} {insert|update|delete}

as 相应T-SQL语句

7. 删除触发器:

?

1

drop trigger trigger_name

8. 查看数据库中已有触发器:

8.1 查看数据库中所有触发器

?

1

select * from sysobjects where xtype='TR'

8.2 查看单个触发器

?

1

exec sp_helptext '触发器名'

9. “Instead of”相关示例:

两张表:学生(学号 int, 姓名 varchar)、借书记录(学号 int, 图书编号 int)

实现功能:在删除学生表时,如果该学生仍有借书记录(未还)则不能删除

?

1

2

3

4

5

6

7

8

alter trigger trigger_学生_Delete

on 学生

instead of Delete

as

begin

    if not exists(select * from 借书记录, deleted where 借书记录.学号 = deleted.学号)

        delete from 学生 where 学生.学号 in (select 学号 from deleted)

end

10. “After”触发器

10.1 在“订单”表中建立触发器,当向“订单”表中插入一条订单记录时,检查“商品”表的货品状态“状态”是否为1(正在整理),则不能往“订单”表加入该订单。

?

1

2

3

4

5

6

7

8

9

10

create trigger trigger_订单_insert

on 订单

after insert

as

    if (select 状态 from 商品, inserted where 商品.pid = inserted.pid)=1

    begin

        print 'the goods is being processed'

        print 'the order cannot be committed'

        rollback transaction --回滚,避免加入

    end

  • 该示例中“pid”为商品编码
  • 该示例的if判断严格来讲是不准确的,因为“订单”表如果每次插入一条记录,该判断没有问题;如果一次插入多条记录,则“select 状态”返回的是多行。

10.2 在“订单”表建立一个插入触发器,在添加一条订单时,减少“商品”表相应的货品记录中的库存。

?

1

2

3

4

5

6

7

create trigger trigger_订单_insert2

on 订单

after insert

as

    update 商品 set 数量 = 数量 - inserted.数量

    from 商品, inserted

    where 商品.pid = inserted.pid

10.3 在“商品”表建立删除触发器,实现“商品”表和“订单”表的级联删除。

?

1

2

3

4

5

create trigger goodsdelete trigger_商品_delete

on 商品

after delete

as

    delete from 订单 where 订单.pid in (select pid from deleted)

10.4 在“订单”表建立一个更新触发器,监视“订单”表的“订单日期”列,使其不能被“update”.

?

1

2

3

4

5

6

7

8

9

create trigger trigger_订单_update

on 订单

after update

as

    if update(订单日期)

    begin

        raiserror('订单日期不能手动修改',10,1)

        rollback transaction

    end

10.5 在“订单”表建立一个插入触发器,保证向“订单”表插入的货品必须要在“商品”表中一定存在。

?

1

2

3

4

5

6

7

8

9

create trigger trigger_订单_insert3

on 订单

after insert

as

    if (select count(*) from 商品, inserted where 商品.pid = inserted.pid)=0

    begin

        print '商品不存在'

        rollback transaction

    end

10.6 “订单”表建立一个插入触发器,保证向“订单”表插入的货品信息要在“订单日志”表中添加

?

1

2

3

4

5

alter trigger trigger_订单_insert

on 订单

for insert

as

    insert into 订单日志 select inserted.Id, inserted.pid,inserted.数量 from inserted

11. 参考资源

  • SQL Server 触发器
  • 关于 INSTEAD OF 触发器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439517.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解协同感知数据集OPV2V: An Open Benchmark Dataset and Fusion Pipeline for Perception with V2V Communication

在《详解自动驾驶仿真框架OpenCDA: An Open Cooperative Driving Automation Framework Integrated with Co-Simulation》 一文中介绍了自动驾驶仿真框架 OpenCDA。本文将介绍论文作者另一篇最新工作 OPV2V,论文收录于 ICRA2022。 OPV2V 数据集主要 feature 有&…

【Python学习】 - 如何在Spyder中弹出plot绘图窗口而不是在Console中绘图

依次选择这几项: 点击ok确认。 注意:点击ok之后不会立即生效,重启Spyder之后才会生效

mysql系列:加深对脏读、脏写、可重复读、幻读的理解

关于相关术语的专业解释,请自行百度了解,本文皆本人自己结合参考书和自己的理解所做的阐述,如有不严谨之处,还请多多指教。 **不可重复读的重点是修改: **同一事务,两次读取到的数据不一样。 幻读的重点在于新增或者…

重读经典(点云深度学习开山之作):《Deep learning on point clouds for 3D scene understanding》(持续更新中)

本文介绍的是 PointNet 作者的博士论文:3D场景理解中的点云深度学习。从上图可以看到,整个博士论文主要贡献有两块:一是点云深度学习的网络架构(PointNet 和 PointNet);二是在3D场景理解中的应用&#xff0…

【Python学习】 - plt画图时,添加标题的中英文问题

默认是只能用中文,如果添加了中文标题,则会输出一堆乱码,解决方法就是加上下面这两行代码。 plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus] False

Coursera自动驾驶课程第17讲:An Autonomous Vehicle State Estimator

在第16讲《Coursera自动驾驶课程第16讲:LIDAR Sensing》我们学习了自动驾驶目前常用的3D 传感器,激光雷达,了解了激光雷达的工作原理,掌握了对点云数据的操作以及如何使用点云配准方法来进行汽车定位。 回顾一下,在本…

!何为脏读、不可重复读、幻读

2.0、前言 事务的隔离性是指多个事务并发执行的时候相互之间不受到彼此的干扰的特性,隔离性是事务ACID特性中的I,根据隔离程度从低到高分为Read Uncommitted(读未提交),Read Committed(读已提交&#xff0…

【Python学习】 - 解决DataFrame占用内存过大问题

这篇文章原文出自kaggle,文中给出了reduce_mem_usage方法可以用来自动缩减dataframe占用空间 这篇notebook展示了通过使用更合理的数据类型来减少dataframe的内存使用量 方法如下: 迭代每一个column 检查column是否为数字型 检查column是否可以用inte…

【转】JPA、Hibernate和Mybatis区别和总结

很多人都用过java的数据库连接池C3P0,但官方没有说明名称的由来。 据传闻:连接池作者是《星球大战》迷,C3P0就是其中的一个机器人,并且这个名称中包涵connection 和pool的单词字母。因此叫这个名字(根据网友提醒&…

详解3D物体检测模型: Voxel Transformer for 3D Object Detection

本文介绍一个新的的3D物体检测模型:VoTr,论文已收录于ICCV 2021。 这是第一篇使用 voxel-based Transformer 做3D 主干网络,用于点云数据3D物体检测。由于有限的感受野,传统的 3D 卷积网络检测器(voxel-based&#xff…

【Python学习】 - Pandas包,对于describe函数和mean函数求平均值的效率问题

经测验,describe函数要快很多,不知道是不是当做一个属性直接存储起来,然后调用函数的时候O1输出? 对于30000*288的数据,describe是秒出结果,但是调用mean函数则需要10秒左右。 对于300000*3左右数据量的数…

一步步编写操作系统 65 标准调用约定stdcall 汇编实战

因为c语言遵循的调用约定是cdecl,咱们也自然要遵守cdecl约定了。不过为了起到对比的作用,除了介绍cdecl外,也会介绍下stdcall。 既然咱们用的是调用约定是cdecl,那对它的介绍最好让它离下一节的内容近一些,所以先说一…

Coursera自动驾驶课程第18讲:The Planning Problem

在第17讲《Coursera自动驾驶课程第17讲:An Autonomous Vehicle State Estimator》 我们学习了如何使用多传感器融合进行自车定位,以及传感器的内外参标定和时间同步,我们还讨论了在实际应用中常遇到的问题。 从本讲开始我们将学习一个新的模…

BI中事实表,维度表和数据集市,数据仓库的理解

维度表(dimension)存放着一些维度属性,例如时间维度:年月日时;地域维度:省份,城市;年龄维度:老年,中年,青年;职称维度:高&…

【Python学习】 - 如何将Pandas包中的groupby分组类型转换成DataFrame(一步就足够了)

输入:df_Grp,类型是pandas.core.groupby.generic.DataFrameGroupBy 我们先来学习一下如何将分组后的其中一个分组给转换成DataFrame类型: tmp dict(list(df_Grp)) tmpname[] tmpname [i for i,j in df_Grp] #下面这行代码其实就转化成Dat…

详解3D物体检测模型:Focal Sparse Convolutional Networks for 3D Object Detection

用于3D目标检测的焦点稀疏卷积神经网络【CVPR2022】【3D检测】本文介绍一篇新的 3D 物体检测模型:Focals Conv,论文收录于 CVPR2022。在 3D 检测任务中,点云或体素数据不均匀地分布在3维空间中,不同位置的数据对物体检测的贡献是不…

地平线:面向规模化量产的自动驾驶感知研发与实践

导读 4月27日,地平线智能驾驶感知研发部负责人苏治中就 《面向规模化量产的自动驾驶感知研发与实践》 这一主题进行了直播讲解。 本次课程内容分为4个部分: 1、地平线自动驾驶环境感知量产实践 2、软硬协同的自动驾驶感知算法设计 3、实现规模化量产的“…

【Python学习】 - 关于DataFrame中的applymap函数 和 Series中的map函数

在用pandas预处理数据时,难免需要自己构造一些有价值的数据,applymap函数和map函数对于处理此类问题十分方便。 给定一个DataFrame,含有每个学生的第一次考试和第二次考试的成绩,现在让你将分数转化成ABCD和 ‘ 不及格 ’ 等级。…

Power BI与Power Query、Power Pivot 是什么关系?

搞不清楚Power BI与Power Query、Power Pivot是什么关系?看这篇文章就够了。 刚开始学习PowerBI的时候,总是能碰到Power Query和Power Pivot这两个词(下文简称为PQ和PP),现在中文里面学习PowerBI的资源本来就不是很多&#xff0c…

地平线:上帝视角与想象力——自动驾驶感知的新范式

导读 3月28日,在「地平线自动驾驶技术专场」上,地平线自动驾驶系统架构师刘景初博士围绕《上帝视角与想象力——自动驾驶感知的新范式 》这一主题进行了直播讲解。 本次课程主要分为以下4个部分: 1、自动驾驶结构演化提出算法新需求 2、软件2…