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.rhkb.cn/news/251825.html

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

相关文章

Linux项目自动化构建工具之make/Makefile演示gcc编译

文章目录 一、背景二、如何使用?三、原理四、关于make的问题五、再次理解/编写makefile依赖关系依赖方法 六、原理讲解项目清理makefile是支持变量的取消执行make后显示命令依赖方法可以多行 一、背景 会不会写makefile,从一个侧面说明了一个人是否具备…

nop-entropy可逆计算入门(1)

第1步:从大佬的gitee:https://gitee.com/canonical-entropy/nop-entropy下载源码,进行本地编译,具体编译看项目下的readme,想偷懒的可以下载我编译后的jar,放到自己的maven仓库 https://pan.baidu.com/s/1p9MOh40MJ2m…

mac如何实现升级node版本、切换node版本

一、 查看node所有版本(前提:安装了nodejs) npm view node versions二、安装指定node版本 sudo n 版本号三、检查目前安装了哪些版本的node,会出现已安装的node版本 n四、切换已安装的node版本 sudo n 版本号其他命令 1、sudo npm cache…

Centos 内存和硬盘占用情况以及top作用

目录 只查看内存使用情况: 内存使用排序取前5个: 硬盘占用情况 定位占用空间最大目录 top查看cpu及内存使用信息 前言-与正文无关 生活远不止眼前的苦劳与奔波,它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&…

Matlab数字图像处理——图像复原与滤波算法应用方法

图像处理领域一直以来都是计算机科学和工程学的一个重要方向,图像复原则是其中一个重要的研究方向之一。图像复原旨在通过运用各种滤波算法,对图像进行去噪、恢复和改善,以提高图像的质量和可视化效果。在本文中,我们将介绍如下内…

python Flask 写一个简易的 web 端程序(附demo)

python Flask 写一个简易的 web 端程序 (附demo) 介绍简单介绍装饰器 app.route("/") 进阶增加接口设置端口 静态网页核心代码完整代码 介绍 Flask 是一个用于构建 Web 应用程序的轻量级 Python Web 框架。它设计简单、易于学习和使用&#x…

ReactNative实现宽度变化实现的动画效果

效果如上图所示,通过修改设备宽度实现动画效果 import React, {useRef, useEffect, useState} from react; import {Animated, Text, View, Image} from react-native;const FadeInView props > {const fadeAnim useRef(new Animated.Value(0)).current;React…

list基本使用

list基本使用 构造迭代器容量访问修改 list容器底层是带头双向链表结构&#xff0c;可以在常数范围内在任意位置进行输入和删除&#xff0c;但不支持任意位置的随机访问&#xff08;如不支持[ ]下标访问&#xff09;&#xff0c;下面介绍list容器的基本使用接口。 template <…

k8s学习-Kubernetes的网络

Kubernetes作为编排引擎管理着分布在不同节点上的容器和Pod。Pod、Service、外部组件之间需要⼀种可靠的方找到彼此并进行通信&#xff0c;Kubernetes网络则负责提供这个保障。 1.1 Kubernetes网络模型 Container-to-Container的网络 当Pod被调度到某个节点&#xff0c;Pod中…

ARM PAC指针认证的侧信道攻击——PACMAN安全漏洞

目录 Q1. PACMAN论文的内容是什么&#xff1f; Q2. Arm处理器是否存在漏洞&#xff1f; Q3. 受Arm合作伙伴架构许可设计的处理器实现是否受到影响&#xff1f; Q4. Cortex-M85受到影响吗&#xff1f; Q5. Cortex-R82受到影响吗&#xff1f; Q6. 指针认证如何保护软件&…

Python 实现 五子棋小游戏【附源码】

引言 五子棋是一种古老而深受欢迎的策略游戏&#xff0c;它具有简单的规则和无穷的变化。作为一种传统的中国棋类游戏&#xff0c;五子棋已经在世界范围内流行起来&#xff0c;并成为智力挑战和休闲娱乐的优秀选择。 规则和玩法&#xff1a; 五子棋使用一个15x15的棋盘&#x…

MIMIC数据库, 使用Python研究万古霉素的剂量 (一)

一、万古霉素 是一种杀菌型 抗生素&#xff0c;抑制细菌细胞壁的合成 万古霉素对以下细菌有效&#xff1a; 大多数革兰阳性球菌和杆菌有抗菌活性&#xff0c;包括几乎所有耐青霉素和头孢菌素的 Staphylococcus aureus 和凝固酶阴性葡萄球菌株 许多菌株 肠球菌 &#xff08;…

【Java报错】显示错误“Error:java: 程序包org.springframework.boot不存在“

使用idea运行项目&#xff0c;显示错误信息如下&#xff1a; 原因是&#xff1a;idea配置的maven加载不到autoconfigure。 解决方案一&#xff1a; 第6步绕过证书语句如下&#xff1a; -Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.allowalltrue 打开终端&am…

2V2无人机红蓝对抗仿真

两架红方和蓝方无人机分别从不同位置起飞&#xff0c;蓝方无人机跟踪及击毁红方无人机 2020a可正常运行 2V2无人机红蓝对抗仿真资源-CSDN文库

【并发编程】原子累加器

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程 ⛺️稳重求进&#xff0c;晒太阳 JDK8之后有专门做累加的类&#xff0c;效率比自己做快数倍以上 累加器性能比较 参数是方法 // supplier 提供者 无中生有 ()->结果// func…

ElasticSearch搜索与分析引擎-Linux离线环境安装教程

目录 一、下载安装包 网盘链接: 二、安装流程及遇到的问题和解决方案 &#xff08;1&#xff09;JDK安装 &#xff08;2&#xff09;Elasticsearch安装 &#xff08;3&#xff09;Kibana安装 ​&#xff08;4&#xff09;Ik分词器安装 三、启动过程中的问题 &#xff…

zabbix监控mariadb数据库

zabbix监控mariadb数据库 1.创建监控用户及授权 [rootchang ~]# mysql -uroot -p123qqq.A MariaDB [(none)]> CREATE USER monitor% IDENTIFIED BY 123qqq.A; MariaDB [(none)]> GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO monitor%; Maria…

【复现】WordPress html5-video-player SQL 注入漏洞_39

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 在WordPress中播放各种视频文件。一个简单&#xff0c;可访问&#xff0c;易于使用和完全可定制的视频播放器&#xff0c;适用于所…

Android SELinux:保护您的移动设备安全的关键

Android SELinux&#xff1a;保护您的移动设备安全的关键 1 引言 移动设备在我们的生活中扮演着越来越重要的角色&#xff0c;我们几乎把所有重要的信息都存储在这些设备上。然而&#xff0c;随着移动应用程序的数量不断增加&#xff0c;安全性也变得越来越关键。这就是为什么…

Android14之Selinux报错:unknown type qemu_device at token (一百八十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…