SQL Server之DML触发器

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

触发器的定义语言如下:

           CREATE [ OR ALTER ] TRIGGER trigger_nameon {table_name | view_name}{for | After | Instead of }[ insert, update,delete ]assql_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
BEGINselect @count = count(*) from authorprint @count
END

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

我们插入前数据条数

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

 

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

alter  TRIGGER authorTrigger ON author INSTEAD OF  INSERT AS
declare @count int
BEGINselect @count = count(*) from authorprint @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
BEGINselect@upflag = casewhen d.IsAddSecurityPlan != i.IsAddSecurityPlan then 1when d.MeterVersion != i.MeterVersion then 1when d.SystemNo != i.SystemNo then 1when d.IsCancel != i.IsCancel then 1when d.UseDate != i.UseDate then 1when d.HankDate != i.HankDate then 1when d.UseYear != i.UseYear then 1when d.AddressCode != i.AddressCode then 1when d.MeterType != i.MeterType then 1when d.UserGasType != i.UserGasType then 1else 0endfrom inserted i left join deleted d on d.id = i.idif(@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.hqwc.cn/news/453013.html

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

相关文章

Kubernetes - 如何利用 K8S 拉取私有仓库镜像

问题描述 最近实战时,发现一个很奇怪的问题,在通过 k8s 创建 pod,拉取镜像时,总是显示如下信息: Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: …

大数据 - Spark系列《四》- Spark分布式运行原理

Spark系列文章: 大数据 - Spark系列《一》- 从Hadoop到Spark:大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 目录 🍠…

Java项目管理01-Maven基础

一、Maven的常用命令和生命周期 1.Maven的常用命令使用方式 complie:编译,将java文件编译为class字节码文件 clean:清理,删除字节码文件 test:测试,运行项目中的test类 package:打包&#x…

[SWPUCTF 2021 新生赛]easyupload1.0

发现是上传文件第一想到是文件木马 <?php eval ($_POST[123]);?>木马上传burp修改后缀发现flag里面这个是假的 我们猜想是在phpinfo我们上传<?php eval(phpinfo(););?>木马上传burp修改后缀里面 CtrlF 发现flag

Oracle 面试题 | 12.精选Oracle高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Packet Tracer - Configuring a Zone-Based Policy Firewall (ZPF)

Packet Tracer - 配置基于区域的策略防火墙&#xff08;ZPF&#xff09; 地址表 目标 在防火墙配置前验证设备之间的连通性。 在路由器R3上配置基于区域的策略&#xff08;ZPF&#xff09;防火墙。 使用ping、Telnet和网页浏览器验证ZPF防火墙功能。 背景/场景 基于区域的…

ROS2学习(一):Ubuntu 20.04 安装 ROS2(Galactic Geochelone)

文章目录 一、ROS2(Galactic Geochelone)介绍二、ROS2(Galactic Geochelone)安装1. 设置语言环境2. 配置ubuntu universe仓库3. 配置ros2 apt仓库4. 安装ros25. 安装情况测试 一、ROS2(Galactic Geochelone)介绍 官方文档 二、ROS2(Galactic Geochelone)安装 1. 设置语言环…

ACM训练题:曲线

这题只需要注意一个点&#xff0c;就是所有二次函数的二次系数都是大于0的&#xff0c;这说明这是个下凸函数&#xff0c;而且最小值旁边都是单调的&#xff0c;对于求区间凸函数极值问题&#xff0c;套三分模板即可。 AC代码&#xff1a; #include<bits/stdc.h> usin…

Ubuntu+GPU搭建Stable-Diffusion教程

【前序】已经安装anaconda 1.git拉取项目到本地 执行git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git 进入项目目录下 cd stable-diffusion-webui/ 2. 安装对应Python依赖包 首先安装pytorch和torchvision&#xff0c;若是GPU环境的用户需要安装与cu…

CSDN文章导出工具

源码地址&#xff1a; github:https://github.com/lishuangquan1987/CSDNExportergitee:https://gitee.com/lishuangquan1987/csdnexporter 介绍 最近有CSDN博客导出来的需求&#xff0c;翻看了很多开源工具&#xff0c;都不能用或者不好用&#xff0c;于是决定自己做一个。…

【Docker】入门到精通(常用命令解读)

一、准备工作 1.配置Docker的yum库 首先要安装一个yum工具 yum install -y yum-utils安装成功后&#xff0c;执行命令&#xff0c;配置Docker的yum源&#xff1a; yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo2.安装Docker 执…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItem组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之MenuItem组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、MenuItem组件 TextClock组件通过文本将当前系统时间显示在设备上。支持不同时…