SQL Server之DML触发器

news2024/11/24 13:56:59

一、如何创建一个触发器呢

触发器的定义语言如下:

           CREATE [ OR ALTER ] TRIGGER trigger_name
           on {table_name | view_name}
           {for | After | Instead of }
           [ insert, update,delete ]
           as
           sql_statement

从这个定义语言我们可以知道如下信息:

  • trigger_name:触发器的名称。 trigger_name 必须遵循标识符规则,但 trigger_name 不得以 # 或 ## 开头。
  • table | view:触发器可以作用于表或视图,只有 INSTEAD OF 触发器才能引用视图
  • FOR | AFTER:FOR 或 AFTER 指定仅当触发 SQL 语句中指定的所有操作都已成功启动时,DML 触发器才触发。
  • INSTEAD OF:指定 DML 触发器(而不是触发 SQL 语句)启动,因此替代触发语句的操作。

 从定义中我们可以发现:DML触发器总体有两种类型:AFTER 触发器和INSTEAD OF 触发器

二、AFTER 触发器和INSTEAD OF 触发器的区别

直接区别它们可能晦涩难懂,我们先举个例子

(1)建一张表

--作家表
CREATE TABLE my_test.dbo.author (
	id bigint IDENTITY(0,1) NOT NULL,
	name varchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL )

(2)在author创建after触发器

CREATE  TRIGGER authorTrigger ON author AFTER  INSERT AS
declare @count int
BEGIN
	select @count = count(*) from author
	print @count
END

该触发器作用就是统计insert后的表数量,测试结果如下:

我们插入前数据条数

 执行insert语句后,触发触发器,输出的条数是

 

(3)修改author的触发器为INSTEAD OF

alter  TRIGGER authorTrigger ON author INSTEAD OF  INSERT AS
declare @count int
BEGIN
	select @count = count(*) from author
	print @count
END

 该触发器作用就是统计insert后的表数量,测试结果如下:

我们插入前数据条数

 

 执行insert语句后,触发触发器,输出的条数是

看到这里,读者可能怀疑数据错了,第二种触发器INSTEAD OF为何插入后还是七条呢,不应该是八条吗

根据这个实验引出结论,

  • after 触发器(insert、update、delete触发器)内的语句是在操作执行之后(已经作用在表上)才触发执行的
  •  instead of 触发器并不会执行操作(不会影响实际的表),它更像一个指令,遇到条件中的指令就触发了,就会执行触发器内的语句。
  • 在执行 INSERT、UPDATE、MERGE 或 DELETE 语句的操作之后执行 AFTER 触发器
  • INSTEAD OF 触发器可用于对一个或多个列执行错误或值检查,然后在插入、更新或删除行之前执行其他操作

 无论after 触发器还是instead of 触发器,他们的作用都是在更新或更新后对表中数据操作,那么更新的旧数据该保存到哪里呢,sqlserver提供了两张临时表inserted 和 deleted 表

三、inserted 和 deleted 表

inserted表和deleted表对照

修改操作记录inserted表deleted表
增加(insert)记录存放新增的记录............
删除(deleted)记录..............存放被删除的记录
修改(update)记录存放更新后的记录存放更新前的记录
  • inserted表保存更新后的记录副本,deleted表保存更新前的记录副本。
  • INSTEAD OF触发器和AFTER 触发器都可以使用inserted表和deleted表
  • SQL Server 会自动创建和管理这两种表,用户使用它们作为条件,但是不能修改表中的数据

四、项目实战

开发中,有这么一个需求:当表中某些字段发生修改或者新增一条记录时,会自动更新表中modifyTime字段为当前时间,如何采用触发器实现呢?

分析:这里要注意是某些字段有更新,才更新modifyTime字段;如果你更新的字段不在指定的字段里,是不会更新modifyTime字段,答案如下:

CREATE  TRIGGER modifMeterTrigger ON
Meter after UPDATE,INSERT AS
declare @upflag int
BEGIN
	select
	@upflag = case
		when d.IsAddSecurityPlan != i.IsAddSecurityPlan then 1
		when d.MeterVersion != i.MeterVersion then 1
		when d.SystemNo != i.SystemNo then 1
		when d.IsCancel != i.IsCancel then 1
		when d.UseDate != i.UseDate then 1
		when d.HankDate != i.HankDate then 1
		when d.UseYear != i.UseYear then 1
		when d.AddressCode != i.AddressCode then 1
		when d.MeterType != i.MeterType then 1
		when d.UserGasType != i.UserGasType then 1
		else 0
	 end
   from inserted i left join deleted d on d.id = i.id
	if(@upflag > 0)
	UPDATE Meter SET ModifTime = GETDATE( )
	FROM Meter t INNER JOIN Inserted i ON t.id=i.id
END

 看这个触发器定义语句,比之前的要复杂好多,我慢慢解读

(1)首先定义的After类型的触发器

(2)定义了一个局部变量,@upflag来标志更新的字段是否在指定的字段内

(3)将inserted和deleted采用左连接,通过case when来判断,如果inserted字段的值不等于deleted中的值,说明指定字段有更新,然后更新标志为@upflag=1

(4)最后判断@upflag是否为1,为1执行更新

(5)采用原表和Inserted内连接主要为了既可以批量更新也可以单条更新

注意一点:我们在更新可能会影响多行数据,如果我们在更新时采用id作为条件

比如如下触发器定义(来源于官方):

CREATE TRIGGER NewPODetail  
ON Purchasing.PurchaseOrderDetail  
AFTER INSERT AS  
   UPDATE PurchaseOrderHeader  
   SET SubTotal = SubTotal + LineTotal  
   FROM inserted  
   WHERE PurchaseOrderHeader.PurchaseOrderID = inserted.PurchaseOrderID ; 

 对于多行插入,示例的 DML 触发器可能不会正确运行,SQL官方提供了@@ROWCOUNT 函数来区分单行插入和多行插入

CREATE TRIGGER NewPODetail3  
ON Purchasing.PurchaseOrderDetail  
FOR INSERT AS  
IF @@ROWCOUNT = 1  
BEGIN  
   UPDATE Purchasing.PurchaseOrderHeader  
   SET SubTotal = SubTotal + LineTotal  
   FROM inserted  
   WHERE PurchaseOrderHeader.PurchaseOrderID = inserted.PurchaseOrderID  
END  
ELSE  
BEGIN  
      UPDATE Purchasing.PurchaseOrderHeader  
   SET SubTotal = SubTotal +   
      (SELECT SUM(LineTotal)  
      FROM inserted  
      WHERE PurchaseOrderHeader.PurchaseOrderID  
       = inserted.PurchaseOrderID)  
   WHERE PurchaseOrderHeader.PurchaseOrderID IN  
      (SELECT PurchaseOrderID FROM inserted)  
END; 

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

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

相关文章

Java 获取操作时区 ZonedDateTime

Java 获取操作时区 ZonedDateTime package com.zhong.timeaddress;import java.time.Clock; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Set;public class TimeAddress {public static void main(String[] args) {// 获取系统默认时区ZoneId…

OIS1 OIS1N OSSR OSSI用途

自记: 还是没有理解了 互补通道与刹车 互补通道与刹车功能是高级寄存器特有的功能。 在使用互补通道时,往往还需要考虑死区等特殊功能。而本文为了简单起见,不再考虑死区区间。通过配置TIMx_CCER寄存器,来使能互补通道&#x…

Spring IOC 之深入分析 Aware 接口

🎬作者简介:大家好,我是小徐🥇☁️博客首页:CSDN主页小徐的博客🌄每日一句:好学而不勤非真好学者 📜 欢迎大家关注! ❤️ AbstractAutowireCapableBeanFacto…

Leetcode—33. 搜索旋转排序数组【中等】

2024每日刷题&#xff08;110&#xff09; Leetcode—33. 搜索旋转排序数组 实现代码 class Solution { public:int search(vector<int>& nums, int target) {int n nums.size();int l 0, r n - 1;while(l < r) {int m l (r - l) / 2;if(nums[m] target) …

1 月 30 日算法练习-数论

唯一分解定理 唯一分解定理指的是&#xff1a;对于任意一个>1的正整数&#xff0c;都可以以唯一的一种方式分解为若干质因数的乘积。 x p 1 k 1 ⋅ p 2 k 2 ⋅ … ⋅ p m k m x p_1^{k_1} \cdot p_2^{k_2} \cdot \ldots \cdot p_m^{k_m} xp1k1​​⋅p2k2​​⋅…⋅pmkm​…

推荐系统(Recommender Systems)

一、问题形式化 在接下来的内容中&#xff0c;我将开始讲解推荐系统的一些理论知识。我们从一个例子开始定义推荐系统&#xff0c;假使我们是一个电影供应商&#xff0c;我们有 5 部电影和 4 个用户&#xff0c;我们要求用户为电影打分 前三部电影是爱情片&#xff0c;后两部是…

整理:汉诺塔简析

大体上&#xff0c;要解决一个汉诺塔问题&#xff0c;就需要解决两个更简单的汉诺塔问题 以盘子数量 3 的汉诺塔问题为例 要将 3 个盘子从 A 移动到 C&#xff0c;就要&#xff1a; 将两个盘子从 A 移动到 B&#xff08;子问题 1&#xff09; 为了解决子问题 1&#xff0c;就…

图论练习4

内容&#xff1a;染色划分&#xff0c;带权并查集&#xff0c;扩展并查集 Arpa’s overnight party and Mehrdad’s silent entering 题目链接 题目大意 个点围成一圈&#xff0c;分为对&#xff0c;对内两点不同染色同时&#xff0c;相邻3个点之间必须有两个点不同染色问构…

高端酒店宴会包间桌位预定小程序h5开源版开发

高端酒店宴会包间桌位预定小程序h5开源版开发 餐厅预定桌位系统&#xff0c;支持多店切换预约&#xff0c;提供全部前后台无加密源代码和数据库 功能特性 为你介绍餐厅预订系统的功能特性 多端适配 采用uniapp,目前适配小程序和微信H5 多店铺 支持多店铺预定 付费和免费预定 支…

数据结构中的时间复杂度和空间复杂度基础

目录 数据结构 数据结构中的基本名词 数据 数据对象 数据元素 数据项 数据类型 数据对象、数据元素和数据项之间的关系 数据结构及分类 逻辑结构 物理结构 算法 算法的特点 算法设计上的要求 算法效率的衡量 时间复杂度 大O渐进表示法 最坏情况和平均情况 常…

【Simulink系列】——动态系统仿真 之 离散系统线性离散系统

一、离散系统定义 离散系统是指系统的输入与输出仅在离散的时间上取值&#xff0c;而且离散的时间具有相同的时间间隔。满足下列条件&#xff1a; ①系统&#xff08;的输入输出&#xff09;每隔固定时间间隔才更新一次。固定时间间隔称为采样时间。 ②系统的输出依赖当前的…

【Spring】Spring 启示录

一、OCP 开闭原则 核⼼&#xff1a;在扩展系统功能时不需要修改原先写好的代码&#xff0c;就是符合OCP原则的&#xff0c;反之修改了原先写好的代码&#xff0c;则违背了OCP原则的 若在扩展系统功能时修改原先稳定运⾏程序&#xff0c;原先的所有程序都需要进⾏重新测试&…

景区导览系统|智能导览|景区电子导览|智慧景区导览|AI智能导览

景区/园区导览系统是必不可少的服务内容&#xff0c;可提供提供指引导航&#xff0c;讲解景点、VR游览、预约购票等服务。随着元宇宙、VR、AR等数字科技的不断发展&#xff0c;导览系统的形式也从传统的纸质地图、指示牌等形式&#xff0c;发展为如今的VR/AR智慧导览。 作为国…

【OpenCV人脸检测】写了个智能锁屏小工具!人离开电脑自动锁屏

文章目录 1. 写在前面2. 设计思路3. 人脸检测4. 程序实现 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向感兴趣的朋…

MacOS Mojavev10.14.6

MacOS Mojave v10.14.6系统安装包是一款专为Mac用户设计的操作系统软件包。Mojave是苹果公司为Mac设备开发的一个操作系统版本&#xff0c;它提供了许多新功能和改进&#xff0c;旨在提高Mac用户的使用体验和工作效率。 安装MacOS Mojave v10.14.6系统后&#xff0c;用户可以享…

从0到1入门C++编程——07 基于多态的职工管理系统

文章目录 一、创建管理类及菜单功能实现二、创建职工抽象类三、退出管理程序四、增加职工信息五、读写文件操作六、显示职工信息七、删除职工信息八、修改职工信息九、查找职工信息十、对职工信息排序十一、清空文件内容十二、工程文件构成 本案例中利用C实现一个基于多态的职工…

flask_django_python五金电商网络营销的可视化分析研究

前面部分完成了系统需求分析&#xff0c;了解到新闻数据业务方面的需求&#xff0c;系统主要分为用户管理、五金信息管理、在线留言、系统管理等功能。销的可视化研究&#xff0c;并对这些数据进行处理&#xff0c; 然后对这些数据进行可视化分析和统计。 Python 爬虫技术目前来…

职言圈:华为4年员工,小金库存到100万,但却在事业上升期决定回老家县城考公务员。

“华为4年员工&#xff0c;小金库存到100万&#xff0c;但却在事业上升期决定回老家县城考公务员。只因不想现在赚的钱将来都花在了医院&#xff01;” 互联网大厂员工的薪资高&#xff0c;这是人尽皆知的事了&#xff0c;特别是像华为、百度、绿厂、阿里、鹅厂等这些知名公司…

Leetcode的AC指南 —— 栈与队列 :1047.删除字符串中的所有相邻重复项

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列 &#xff1a;1047.删除字符串中的所有相邻重复项 **。题目介绍&#xff1a;给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&a…

CG-FS 风速传感器 485型三杯式风速计 气象环境监测仪器

产品概述 本产品主要采用优质聚合物碳纤维为原材料&#xff0c;具有良好的防腐、防侵蚀等特点&#xff0c;能够保证仪器长期使用不起锈&#xff0c;同时配合内部顺滑的轴承系统&#xff0c;确保了信息采集的准确性。外型小巧轻便&#xff0c;便于携带和组装&#xff0c;三杯设…