INSTEAD OF触发器工作原理

INSTEAD OF表示并不执行其所定义的操作INSERT,UPDATE ,DELETE,而仅是执行触发器本身,即当对表进行INSERT、UPDATE 或 DELETE 操作时,系统不是直接对表执行这些操作,而是把操作内容交给触发器,让触发器检查所进行的操作是否正确,如正确才进行相应的操作。因此,INSTEAD OF 触发器的动作要早于表的约束处理。
既可以在表上定义INSTEAD OF触发器,也可以在视图上定义。

传递给为表定义的 INSTEAD OF 触发器的插入的和删除的表与传递给 AFTER 触发器的插入的和删除的表遵守相同的规则。 插入的和删除的表的格式与在其上定义 INSTEAD OF 触发器的表的格式相同。 插入的和删除的表中的每一列都直接映射到基表中的列。

以下是关于引用带 INSTEAD OF 触发器的表的 INSERT 或 UPDATE 语句何时必须提供列值的规则,当引用的表不带 INSTEAD OF 触发器时也一样:

  • 不能为计算列或具有 timestamp 数据类型的列指定值。

  • 不能为具有 IDENTITY 属性的列指定值,除非该表的 IDENTITY_INSERT 为 ON。 当 IDENTITY_INSERT 为 ON 时,INSERT 语句必须提供一个值。

  • INSERT 语句必须为所有无 DEFAULT 约束的 NOT NULL 列提供值。

  • 对于除计算,identity 之外的任何列或timestamp列值都是可选的任何允许空值的列或列具有 DEFAULT 定义的 NOT NULL。

    当 INSERT、UPDATE 或 DELETE 语句引用具有 INSTEAD OF 触发器的视图时, 数据库引擎 将调用该触发器,而不是对任何表采取任何直接操作。 即使插入的和删除的表中为该视图生成的信息格式不同于基表中的数据格式,触发器也必须使用插入的和删除的表中的信息来生成实现基表中请求的操作所需的任何语句。

INSTEAD OF触发器创建

语法:

--声明数据库应用。
use 数据库名;
go

--判断是否已存在触发器,如果已存在则删除。
if exists(select * from sysobjects where name=触发器名)
drop trigger 触发器名;
go

--执行创建触发器
create

--触发器关键字
trigger

--DML 触发器所属架构的名称。 DML 触发器的作用域是为其创建该触发器的表或视图的架构。 不能为 DDL 或登录触发器指定
--[dbo.]
--触发器名称
[架构名.]{ 表名 | 视图名}

on

--对其执行 DML 触发器的表或视图,有时称为触发器表或触发器视图。 可以根据需要指定表或视图的完全限定名称。 视图只能被 INSTEAD OF 触发器引用。 不能对局部或全局临时表定义 DML 触发器。
[架构名.]触发器名

with
--对CREATE TRIGGER 语句的文本进行模糊处理。使用WITH ENCRYPTION可以防止将触发器作为SQL Server复制的一部分进行发布。不能为 CLR 触发器指定 WITH ENCRYPTION。(指定此选项将为触发器加密)
[encryption][,]

--指示触发器已本机编译。 (只能应用于table)
--内存优化表上的触发器需要使用此选项。
--[native_compilation][,]

--确保不能删除或更改触发器引用的表。(只能应用于table)
--内存优化表上的触发器需要使用此选项,但此选项不支持传统表上的触发器。
[schemabinding][,]

--EXECUTE AS (后面可以跟函数,存储过程等)
--指定用于执行该触发器的安全上下文。 允许您控制 SQL Server 实例用于验证被触发器引用的任意数据库对象的权限的用户帐户。
--内存优化表上的触发器需要使用此选项。
--[execute as clause]

--指定执行 DML 触发器而不是触发 SQL 语句,因此,其优先级高于触发语句的操作。 不能为 DDL 或登录触发器指定 INSTEAD OF。
--对于表或视图,每个 INSERT、UPDATE 或 DELETE 语句最多可定义一个 INSTEAD OF 触发器。 但是,可以为具有自己的 INSTEAD OF 触发器的多个视图定义视图。
--INSTEAD OF 触发器不可以用于使用 WITH CHECK OPTION 的可更新视图。 如果将 INSTEAD OF 触发器添加到指定了 WITH CHECK OPTION 的可更新视图中,则 SQL Server 将引发错误。 用户须用 ALTER VIEW 删除该选项后才能定义 INSTEAD OF 触发器。
instead of

--指定数据修改语句,这些语句可在 DML 触发器对此表或视图进行尝试时激活该触发器。 必须至少指定一个选项。 在触发器定义中允许使用上述选项的任意顺序组合。
--对于 INSTEAD OF 触发器,不允许对具有指定级联操作 ON DELETE 的引用关系的表使用 DELETE 选项。 同样,也不允许对具有指定级联操作 ON UPDATE 的引用关系的表使用 UPDATE 选项。
{ [insert] [,] [update] [,] [delete] }

--指定应该再添加一个现有类型的触发器。 WITH APPEND 不能与 INSTEAD OF 触发器一起使用。如果显式声明了 AFTER 触发器,则也不能使用该子句。
--仅当为了向后兼容而指定了 FOR 时(但没有 INSTEAD OF 或 AFTER)时,才能使用 WITH APPEND。 如果指定了 EXTERNAL NAME(即触发器为 CLR 触发器),则不能指定 WITH APPEND。
--with append

--指示当复制代理修改涉及到触发器的表时,不应执行触发器。
--not for replication
as
begin

  sql_statement
end
go

示例:

--声明数据库应用。
use testss;
go

--判断是否已存在触发器,如果已存在则删除。
if exists(select * from sysobjects where name='insteadoftri')
drop trigger insteadoftri;
go

--执行创建触发器
create

--触发器关键字
trigger

--DML 触发器所属架构的名称。 DML 触发器的作用域是为其创建该触发器的表或视图的架构。 不能为 DDL 或登录触发器指定
--[dbo.]
--触发器名称
dbo.insteadoftri

on

--对其执行 DML 触发器的表或视图,有时称为触发器表或触发器视图。 可以根据需要指定表或视图的完全限定名称。 视图只能被 INSTEAD OF 触发器引用。 不能对局部或全局临时表定义 DML 触发器。
dbo.test1

with
--对CREATE TRIGGER 语句的文本进行模糊处理。使用WITH ENCRYPTION可以防止将触发器作为SQL Server复制的一部分进行发布。不能为 CLR 触发器指定 WITH ENCRYPTION。(指定此选项将为触发器加密)
encryption,

--指示触发器已本机编译。 (只能应用于table)
--内存优化表上的触发器需要使用此选项。
--[native_compilation][,]

--确保不能删除或更改触发器引用的表。(只能应用于table)
--内存优化表上的触发器需要使用此选项,但此选项不支持传统表上的触发器。
schemabinding

--EXECUTE AS (后面可以跟函数,存储过程等)
--指定用于执行该触发器的安全上下文。 允许您控制 SQL Server 实例用于验证被触发器引用的任意数据库对象的权限的用户帐户。
--内存优化表上的触发器需要使用此选项。
--[execute as clause]

--指定执行 DML 触发器而不是触发 SQL 语句,因此,其优先级高于触发语句的操作。 不能为 DDL 或登录触发器指定 INSTEAD OF。
--对于表或视图,每个 INSERT、UPDATE 或 DELETE 语句最多可定义一个 INSTEAD OF 触发器。 但是,可以为具有自己的 INSTEAD OF 触发器的多个视图定义视图。
--INSTEAD OF 触发器不可以用于使用 WITH CHECK OPTION 的可更新视图。 如果将 INSTEAD OF 触发器添加到指定了 WITH CHECK OPTION 的可更新视图中,则 SQL Server 将引发错误。 用户须用 ALTER VIEW 删除该选项后才能定义 INSTEAD OF 触发器。
instead of

--指定数据修改语句,这些语句可在 DML 触发器对此表或视图进行尝试时激活该触发器。 必须至少指定一个选项。 在触发器定义中允许使用上述选项的任意顺序组合。
--对于 INSTEAD OF 触发器,不允许对具有指定级联操作 ON DELETE 的引用关系的表使用 DELETE 选项。 同样,也不允许对具有指定级联操作 ON UPDATE 的引用关系的表使用 UPDATE 选项。
insert,update,delete

--指定应该再添加一个现有类型的触发器。 WITH APPEND 不能与 INSTEAD OF 触发器一起使用。如果显式声明了 AFTER 触发器,则也不能使用该子句。
--仅当为了向后兼容而指定了 FOR 时(但没有 INSTEAD OF 或 AFTER)时,才能使用 WITH APPEND。 如果指定了 EXTERNAL NAME(即触发器为 CLR 触发器),则不能指定 WITH APPEND。
--with append

--指示当复制代理修改涉及到触发器的表时,不应执行触发器。
not for replication
as
begin
if (select count(1) from inserted) = 1 and (select count(1) from deleted) = 0
begin
print('insert');
insert into dbo.test1(name,sex,age,classid,height,xml1,xml2)
select top 1 name,sex,age,classid,height,xml1,xml2 from inserted order by id desc;
end
else if (select count(1) from deleted) = 1 and (select count(1) from inserted) = 0
begin
print('delete');
delete from dbo.test1 where id=(select top 1 id from deleted order by id desc);
end
else
begin
print('update');
update dbo.test1 set name=inserted.name,sex=inserted.sex,age=inserted.age,classid=inserted.classid,height=inserted.height,
xml1=inserted.xml1,xml2=inserted.xml2
from inserted
where dbo.test1.id=(select top 1 id from deleted order by id desc);
end
end
go

示例结果:

INSTEAD OF触发器优缺点

优点:

  1、可以实现在对数据操作之前更严格的检查和校验。

  2、可定义在表上,也可以定义在视图上,同一操作只能定义一个。

  3、指定执行 DML 触发器而不是触发 SQL 语句,因此,其优先级高于触发语句的操作。

缺点:

  1、可移植性差。

  2、占用服务器资源,给服务器造成压力。

  3、执行速度主要取决于数据库服务器的性能与触发器代码的复杂程度。

  4、触发器会使编程时源码的结构被迫打乱,为将程序修改、源码阅读带来困难。

SQLServer之创建INSTEAD OF INSERT,UPDATE,DELETE触发器的更多相关文章

  1. PHP5: mysqli 插入, 查询, 更新和删除 Insert Update Delete Using mysqli (CRUD)

    原文: PHP5: mysqli 插入, 查询, 更新和删除  Insert Update Delete Using mysqli (CRUD) PHP 5 及以上版本建议使用以下方式连接 MySQL ...

  2. SQLServer之创建DML AFTER INSERT触发器

    DML AFTER INSERT触发器创建原理 触发器触发时,系统自动在内存中创建deleted表或inserted表,内存中创建的表只读,不允许修改,触发器执行完成后,自动删除. insert触发器 ...

  3. insert update delete 语法 以及用法

    insert update delete 被称为 数据定义语句语句 也就是数据的增加 修改 删除 其中不包括查询 譬如: create database -创建数据库 alter database - ...

  4. sql中同一个Trigger里同时包含Insert,Update,Delete

    sql中同一个Trigger里同时包含Insert,Update,Delete SQLServer是靠Inserted表和Deleted表来处理的,判断一下就可以了,只不过比ORACLE麻烦一点 cr ...

  5. LINQ体验(9)——LINQ to SQL语句之Insert/Update/Delete操作

    我们继续讲解LINQ to SQL语句,这篇我们来讨论Insert/Update/Delete操作.这个在我们的程序中最为常用了.我们直接看例子. Insert/Update/Delete操作 插入( ...

  6. JDBC基础篇(MYSQL)——使用statement执行DML语句(insert/update/delete)

    注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package day02_statement; import java.sql.Connection; import java.s ...

  7. 关于MyBatis mapper的insert, update, delete返回值

    这里做了比较清晰的解释: http://mybatis.github.io/mybatis-3/java-api.html SqlSession As mentioned above, the Sql ...

  8. mysql 事务是专门用来管理insert,update,delete语句的,和select语句一点不相干

    1.mysql 事务是专门用来管理insert,update,delete语句的,和select语句一点不相干 2.一般来说,事务是必须满足4个条件(ACID): Atomicity(原子性).Con ...

  9. [Hive - LanguageManual] DML: Load, Insert, Update, Delete

    LanguageManual DML Hive Data Manipulation Language Hive Data Manipulation Language Loading files int ...

随机推荐

  1. 动手实现一个 LRU cache

    前言 LRU 是 Least Recently Used 的简写,字面意思则是最近最少使用. 通常用于缓存的淘汰策略实现,由于缓存的内存非常宝贵,所以需要根据某种规则来剔除数据保证内存不被撑满. 如常 ...

  2. Zabbix系列之七——添加磁盘IO监测

    zabbix给我们提供了一些较常用的监控模板,但现在我们如果想要监控我们磁盘的IO,这时候zabbix并没有给我们提供这么一个模板,所以我们需要自己来创建一个模板来完成磁盘IO的监控. 1. [roo ...

  3. TP3.2框架中的字母函数解析

    C的使用方法以及注意事项 使用方法: 1.读取配置 C('参数名称')  配置参数不区分大小写,存在则设置,否则返回NULL; 因为配置参数是全局有效的,因此C方法可以在任何地方读取任何配置,即使某个 ...

  4. asp.net core 系列 10 配置configuration (上)

    一.  ASP.NET Core 中的配置概述 ASP.NET Core 中的应用配置是基于键值对,由configuration 程序提供. configuration  将从各种配置源提供程序操作键 ...

  5. 基础才是重中之重~lock和monitor的区别

    回到目录 Monitor的介绍 1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中 ...

  6. 二进制安装部署kubernetes集群---超详细教程

    本文收录在容器技术学习系列文章总目录 前言:本篇博客是博主踩过无数坑,反复查阅资料,一步步搭建完成后整理的个人心得,分享给大家~~~ 本文所需的安装包,都上传在我的网盘中,需要的可以打赏博主一杯咖啡钱 ...

  7. [十]基础数据类型之Unicode编码简介

    编码含义 关于编码的含义,之前也说过,计算机只能存储二进制序列 所以对于字符,保存的时候,需要进行编码为二进制,进行存储 呈现的时候,需要将二进制进行解码,转换成字符的形式   有很多种编码方式,比如 ...

  8. Java提高班(二)深入理解线程池ThreadPool

    本文你将获得以下信息: 线程池源码解读 线程池执行流程分析 带返回值的线程池实现 延迟线程池实现 为了方便读者理解,本文会由浅入深,先从线程池的使用开始再延伸到源码解读和源码分析等高级内容,读者可根据 ...

  9. 表达式目录树(Expression)

    一:什么是表达式树 Expression我们称为是表达式树,是一种数据结构体,用于存储需要计算,运算的一种结构,这种结构可以只是存储,而不进行运算.通常表达式目录树是配合Lambda一起来使用的,la ...

  10. IEnumerable<T>和IQueryable<T>区分

    LINQ查询方法一共提供了两种扩展方法,在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展:Queryab ...