触发器

举报
Tracy 发表于 2019/09/02 12:16:57 2019/09/02
【摘要】 定义: 触发器是一种特殊类型的存储过程,触发器主要是通过实践进行触发而被执行,在存储过程中可以通过存储过程名字而被直接调用。但是用户不可直接调用。作用: 实现有主键和外键所不能保证的复杂的参照完整性和数据的一致性。除此之外还有如下一些功能: (1) 强化约束(Enforce restriction) 触发器能够实现比CHECK 语句更为复杂的约束。 (2) 跟踪变化Auditing ch...

定义:

触发器是一种特殊类型的存储过程,触发器主要是通过实践进行触发而被执行,在存储过程中可以通过存储过程名字而被直接调用。但是用户不可直接调用。

作用:

实现有主键和外键所不能保证的复杂的参照完整性和数据的一致性。除此之外还有如下一些功能:

(1) 强化约束(Enforce restriction) 

触发器能够实现比CHECK 语句更为复杂的约束。 

(2) 跟踪变化Auditing changes 

触发器可以侦测数据库内的操作,从而不允许数据库中未经许可的指定更新和变化。 

(3) 级联运行(Cascaded operation)。 

触发器可以侦测数据库内的操作,并自动地级联影响整个数据库的各项内容。例如,某个表上的触发器中包含有对另外一个表的数据操作(如删除,更新,插入)而该操作又导致该表上触发器被触发。 

(4) 存储过程的调用(Stored procedure invocation)。 

为了响应数据库更新触,发器可以调用一个或多个存储过程,甚至可以通过外部过程的调用而在DBMS( 数据库管理系统)本身之外进行操作。 

由此可见,触发器可以解决高级形式的业务规则或复杂行为限制以及实现定制记录等一些方面的问题。例如,触发器能够找出某一表在数据修改前后状态发生的差异,并根据这种差异执行一定的处理。此外一个表的同一类型(INSERT、 UPDATE、 DELETE)的多个触发器能够对同一种数据操作采取多种不同的处理。 

总体而言,触发器性能通常比较低。当运行触发器时,系统处理的大部分时间花费在参照其它表的这一处理上,因为这些表既不在内存中也不在数据库设备上,而删除表和插入表总是位于内存中。可见触发器所参照的其它表的位置决定了操作要花费的时间长短。

如何使用:

(1) 针对较为复杂的跨多表的数据业务级别的约束,可以通过触发器来替代大量的后台判断代码,效率较高且便捷。 

(2) 如果想通过触发器辅助业务逻辑,不能单着眼于数据库内容的变化来设计触发器,还必须紧密结合业务模型中涉及该表的所有地方,因为很有可能因为不一致的逻辑处理方式导致我们设计的触发器遗漏下一些分支条件!其实,在这种情况下,如果能有更好的方法,不建议使用触发器,因为牵扯到过多的业务逻辑内容的话,会使触发器的设计和编写困难重重,不能充分发挥其便捷高效的优点。 

(3) 鉴于触发器在实际运行的时候,是被包含在一个数据库事务中的,所以我们在编写了完整的处理分支后,就可以完全信赖它的执行,大量并发情况下,数据库会自动处理好对各事务的操作,不用担心触发器的性能和正确性。 

(4) 在同一个事务中的不同执行语句,如果后面语句中的操作触发了相应表的触发器,则在触发器内可以查看前面语句执行后的结果列表的内容,所以,在使用触发器的时候,对事物中多条语句的操作的顺序是要考虑清楚的。 

(5) 如果我们使用触发器+数据表的形式来对数据进行一些统计性的操作的时候,我们在保证触发器逻辑完整性的前提下,最好能通过数据库任务的方式来定时进行检查,因为触发器对于一个用程序的操作都能有相应的处理,但对于人为的数据库操作有时却是无能为力的,所以,为了避免这样的错误发生,有必要对统计结果做定期的校验,保证数据的正确性,当然,如果可以,尽量不要使用这种方法,但在一些个性化项目中,因为一些特别的原因,可能会有所应用。 

(6) 我们可以间接地通过更新数据表的方式来调试触发器,当然,也可以通过在触发器中添加一些“特殊的日志性质的更新语句”来辅助我们的调试。 

应用的例子:

1. 利用触发器实现表约束机制(如:PRIMARY KEY、FOREIGN KEY、CHECK等)无法实现的复杂的引用完整性;

2. 利用触发器实现复杂的事务规则(如:想确保薪水增加量不超过25%);

3. 利用触发器维护复杂的缺省值(如:条件缺省);

4. 利用触发器实现复杂的审计功能;

5. 利用触发器防止非法的操作。

语法:

1、表触发器:用户可使用触发器定义语句(CREATE TRIGGER)在一张基表上创建触发器

CREATE [OR REPLACE] TRIGGER [ <模式名> .] <触发器名> [WITH ENCRYPTION] 

 <触发限制描述> [REFERENCING OLD [ROW] [AS] <引用变量名> | NEW [ROW] [AS] <引用变量名> | OLD [ROW] 

[AS] <引用变量名> NEW [ROW] [AS] <引用变量名> ] [FOR EACH {ROW | STATEMENT}] [

WHEN <条件表达式> ]

 <触发器体> <触发限制描述> ::= <触发限制描述1> | <触发限制描述2>

 <触发限制描述1> ::= {BEFORE | AFTER <触发事件> {OR <触发事件> } ON <触发表名>

 <触发限制描述2> ::= INSTEAD OF <触发事件> {OR <触发事件> } ON <触发视图名> <触发表名> ::=[ <模式名> .] <基表名>

参数 

1. <触发器名> 指明被创建的触发器的名称;

2.BEFORE 指明触发器在执行触发语句之前激发; 

3.AFTER 指明触发器在执行触发语句之后激发; 

4.INSTEAD OF 指明触发器执行时替换原始操作;

5. <触发事件> 指明激发触发器的事件,可以是INSERT、DELETE或UPDATE,其中UPDATE事件可通过UPDATE OF <触发列清单> 的形式来指定所修改的列; 

6. <基表名> 指明被创建触发器的基表的名称; 

7.WITH ENCRYPTION 选项,指定是否对触发器定义进行加密; 

8.REFERENCING子句 指明相关名称可以在元组级触发器的触发器体和WHEN子句中利用相关名称来访问当前行的新值或旧值,缺省的相关名称为OLD和NEW; 

9. <引用变量名> 标识符,指明行的新值或旧值的相关名称; 

10.FOR EACH子句 指明触发器为元组级或语句级触发器。FOR EACH ROW表示为元组级触发器,它为被触发命令影响且WHEN子句的表达式计算为真的每条记录激发一次。FOR EACH STATEMENT为语句级触发器,它对每个触发命令执行一次。语句级触发器的FOR EACH子句可以省略; 

11.WHEN子句 只允许为元组级触发器指定WHEN子句,它包含一个布尔表达式,当表达式的值为TRUE时,执行触发器;否则,跳过该触发器; 

12. <触发器体> 触发器被触发时执行的SQL过程语句块。

2、事件触发器:用户可使用触发器定义语句(CREATE TRIGGER)在数据库全局对象上创建触发器。

CREATE [OR REPLACE] TRIGGER [ <模式名> .] <触发器名> [WITH ENCRYPTION] 

BEFORE| AFTER <触发事件子句> ON <触发对象名>  

[WHEN <条件表达式> ] 

 <触发器体>  

 <触发事件子句> := | <系统事件子句>  

 := {OR } := | | | | |

 <系统事件子句> := <系统事件> {OR <系统事件> } 

 <系统事件> := | | | | | | |  

 <触发对象名> :=[ <模式名> .]{SCHEMA|DATABASE>}

参数:

1. <模式名> 指明被创建的触发器的所在的模式名称或触发事件发生的对象所在的模式名,缺省为当前模式; 

2. <触发器名> 指明被创建的触发器的名称; 

3.BEFORE 指明触发器在执行触发语句之前激发; 

4.AFTER 指明触发器在执行触发语句之后激发;

5. 指明激发触发器的DDL事件,可以是CREATE、ALTER、DROP、GRANT、REVOKE、TRUNCATE等; 

6. <系统事件子句> LOGIN、LOGOUT、SERERR、BACKUP DATABASE、RESTORE DATABASE、AUDIT、NOAUDIT、TIMER;

7.WITH ENCRYPTION 选项,指定是否对触发器定义进行加密; 

8.WHEN子句 只允许为元组级触发器指定WHEN子句,它包含一个布尔表达式,当表达式的值为TRUE时,执行触发器;否则,跳过该触发器; 

9. <触发器体> 触发器被触发时执行的SQL过程语句块。

删除触发器:

DROP TRIGGER [ <模式名> .] <触发器名> ;

禁止和启动触发器:

ALTER TRIGGER [ <模式名> .] <触发器名> DISABLE | ENABLE;

重编触发器:

ALTER TRIGGER [ <模式名> .] <触发器名> COMPILE [DEBUG];--[DEBUG]可忽略

本文转载自异步社区。

文链接:

https://www.epubit.com/articleDetails?id=Nc24dc350-b3be-4342-9e51-7b66e3b9d797

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。