关于南大通用GBase 8s的DML触发器的讨论

原文链接:www.gbase.cn/community/p...

更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。

南大通用GBase8s数据库的DML触发器功能,能够帮助开发者实现自动化任务、数据审计、数据完整性保护等多种应用场景。本文将详细介绍GBase8s中DML触发器的语法、特性、使用示例以及一些最佳实践,帮助您更好地理解和应用这一功能。

DML 触发器简介

GBase8s的DML触发器语法,须 SQLMODE 在 ORACLE 兼容模式下执行

arduino 复制代码
set environment sqlmode 'oracle'; 

DML 触发器定义

当某些数据操作事件发生时,数据库应该采取的操作。在相关的事件发生时,由数据库自动地隐式地激发语句集合,即直到一个语句激发的所有触发器执行完成之后该语句才结束,而其中任何一个触发器执行的失败都将导致该语句的失败。

DML 触发器在表上创建,其触发事件由 DML 语句DELETE、INSERT和UPDATE 组成。

DML 触发器语法

  • create [or replace] trigger [databasename.]trigger_name ------触发器名称

  • {before|after} ------触发时间

  • { DELETE | INSERT | UPDATE [ OF column [, column ]... ] }

    OR { DELETE \| INSERT \| UPDATE \[ OF column \[, column\]... \] }... ------触发事件

  • REFERENCING { OLD \[ AS \] old \| NEW \[ AS \] new}...\]\[ FOR EACH ROW \] ------触发级别

  • PLSQL块 ------触发体

从上述语法可以看到,dml触发器由触发时间、触发时间、触发事件等组成,相关概念解释如下:

  • 触发时间:触发事件和该 TRIGGER 的操作顺序。 BEFORE 指明触发器在执行触发语句之前激发;AFTER 指明触发器在执行触发语句之后激发。

  • 触发事件:引起触发器被触发的 DML 语句事件,包括 INSERT 、DELETE 、UPDATE 。

  • 触发对象:被定义触发器的数据库对象,当前版本仅支持基表。

  • 触发操作/触发体:即该 TRIGGER 被触发之后要执行的 PLSQL 语句块。

  • 触发级别:即语句级触发器和行级触发器。

    • 语句级触发器:是指当某触发事件发生时,该触发器只执行一次;
    • 行级触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次,使用 FOR EACH ROW 定义。
  • 触发模式:设置触发器为启用(ENABLE)或禁用(DISABLE)。

  • 触发条件:由 WHEN 子句指定一个逻辑表达式。必须在行级触发器下使用,即必须与FOR EACH ROW 一同使用。只有当该表达式的值为 TRUE 时,遇到触发事件才会自动执行触发器,使其执行触发操作。

DML 触发器中新、旧行值的引用

仅在行级触发器,可以使用新、旧行值的引用访问正在处理的行中的数据。

缺省的引用名是:OLD、:NEW,可使用REFERENCING 子句修改。

:OLD 表示记录被处理前的值;

:NEW 表示记录被处理后的值。

在触发体内,使用以下语法引用新旧行的字段:

:引用名.列名

:OLD、:NEW不同触发事件下含义如下:

触发事件 :OLD :NEW
INSERT 报错处理 该语句结束时将插入的值
UPDATE 更新前的旧值 该语句结束时将更新的值
DELETE 删除前的旧值 报错处理

DML 触发器中触发体的补充说明

DML触发器的触发体是由PLSQL块语法定义。SQLMODE 在 ORACLE 兼容模式下,触发器触发体定义需支持 PLSQL语法定义。

ini 复制代码
<触发体> ::=
[ DECLARE <声明部分>]
BEGIN
<执行部分>
END [触发器名称];

当前版本已实现的 PLSQL 语法在触发体部分均支持。

DML 触发器使用举例

注意:以下所用示例使用的数据库版本为:GBase8sV8.8_TL_3.5.1_x86_64

用例1:多个触发事件的DML触发器

sql 复制代码
> create table emp(empno int,ename varchar2(20),job  varchar2(20),deptno int,sal float) ;

Table created.

> insert into emp values (7777,'tim','tester',20,5000);

1 row(s) inserted.

> insert into emp values (8888,'carry','SALES',10,6000);

1 row(s) inserted.

> create table emp_log(dml_user char(20),dml_type char(20),dml_time char(30));

Table created.

##创建多个触发事件的触发器
> create or replace trigger emp_dml_tri  AFTER  INSERT OR UPDATE OR DELETE ON emp
DECLARE
dml_type char(10);
BEGIN
if INSERTING then
dml_type :='INSERT';
elsif UPDATING then
dml_type :='UPDATE';
elsif DELETING then
dml_type :='DELETE';
END if;
INSERT   INTO emp_log VALUES(user,dml_type,to_char(SYSDATE,'yyyy-mm-dd hh24:mi:ss'));
END;
/
Trigger created.
##分别对对法对象 emp这个表进行delete、update和insert操作,则应该分别向emp_log
中插入用一条记录
> DELETE FROM emp WHERE deptno=20;

1 row(s) deleted.

> UPDATE emp set sal=sal+100;

1 row(s) updated.

> insert into emp values (6666,'rose','tester',20,6000);

1 row(s) inserted.

> SELECT * FROM emp_log;

DML_USER             DML_TYPE             DML_TIME

root                 DELETE               2025-01-15 14:23:48
root                 UPDATE               2025-01-15 14:23:54
root                 INSERT               2025-01-15 14:23:55

3 row(s) retrieved.

用例2:禁用/启用触发器

shell 复制代码
##禁用 emp_dml_tri 触发器
> Alter  trigger   emp_dml_tri disable;

Mode set.
#查看触发器的状态为DISABLED
>   select TRIGGER_NAME,TABLE_NAME,STATUS from USER_TRIGGERS;

TRIGGER_NAME  EMP_DML_TRI
TABLE_NAME    EMP
STATUS        DISABLED

1 row(s) retrieved.

##启用 emp_dml_tri 触发器
> Alter  trigger   emp_dml_tri enable;

Mode set.

#查看触发器的状态为ENABLED
>   select TRIGGER_NAME,TABLE_NAME,STATUS from USER_TRIGGERS;

TRIGGER_NAME  EMP_DML_TRI
TABLE_NAME    EMP
STATUS        ENABLED

1 row(s) retrieved.

用例3:删除触发器

sql 复制代码
drop trigger tri_ins_company;

说明:删除触发器的触发对象后,其相关的触发器都会被自动删除。

用例4:新旧值的引用_insert_新值

sql 复制代码
> create table tab1(tid int, tname varchar2(20),tage int);

Table created.

> create or replace trigger tri_new1 before insert on tab1
Referencing old as old_value  new as new_value for each row
When (new_value.tid<100)
Begin
:new_value.tage :=0;
End;
/
Trigger created.

> insert into tab1 values(100,'yang',20);

1 row(s) inserted.

> insert into tab1 values(90,'li',10);

1 row(s) inserted.
#第二条记录新值小于100,触发器触发,tage值为0
> select * from tab1;


        TID TNAME                        TAGE

        100 yang                           20
         90 li                              0

2 row(s) retrieved.

用例5:新旧值的引用_insert_旧值

sql 复制代码
##接上面用例,insert 时,引用了:OLD,预期报错
>   create or replace trigger tri_new before insert on tab1
Referencing old as old_value  new as new_value for each row
When (new_value.tid<100)
Begin
:new_value.tage :=:old_value.tage+1 ;
End;
/

Trigger created.

>   insert into tab1 values(90,'li',10);

  732: Incorrect use of old or new values correlation name inside trigger.
Error in line 1
Near character position 2

用例6:新旧值的引用_delete_旧值

sql 复制代码
> create table tab3(tid int, tname varchar2(20),tage int);

Table created.

> insert into tab3 values(100,'yang',20);

1 row(s) inserted.

> insert into tab3 values(90,'li',10);

1 row(s) inserted.

> create table tab4 as select * from tab3 where 1=2;

0 row(s) retrieved into table.

> create or replace trigger tri_new1 after  delete on tab3
Referencing old as old  new as new for each row
Begin
Insert into tab4 values(:old.tid,:old.tname,:old.tage);
End;
/
Trigger created.
> Delete from tab3 where tid=90;

1 row(s) deleted.

> select * from tab4;

        TID TNAME                        TAGE

         90 li                             10

1 row(s) retrieved.

用例7:新旧值的引用_delete_新值

sql 复制代码
##接上面用例,delete 时,引用了:new,预期报错
create or replace trigger tri_new1 after  delete on tab3
Referencing old as old  new as new for each row
Begin
Insert into tab4 values(:new.tid,:old.tname,:old.tage);
End;
/
Trigger created.

>   Delete from tab3 where tid=100;
  732: Incorrect use of old or new values correlation name inside trigger.
Error in line 1
Near character position 2

以上为DML触发器使用的简单介绍,通过合理使用DML触发器,可以显著提高数据库的自动化程度和数据管理效率。希望本文的介绍和示例能够帮助您更好地理解和应用DML触发器。如果您有任何疑问或需要进一步的帮助,欢迎随时在社区中提问。

原文链接:www.gbase.cn/community/p...

更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。

相关推荐
聪明的墨菲特i41 分钟前
SQL进阶知识:三、事务控制
数据库·sql·mysql·数据库开发·事务控制
·薯条大王1 小时前
Node.js 开发用户登录功能(使用mysql实现)
数据库·mysql·node.js
朴拙数科1 小时前
基于Python将MongoDB文本数据通过text2vec-large-chinese模型向量化并存储到Milvus数据库的完整实现方案
数据库·python·mongodb
咸鱼睡不醒_2 小时前
CentOS7安装MySQL教程
数据库·mysql
E___V___E2 小时前
黑马点评redis改 part 5
数据库·redis·缓存
打码人的日常分享2 小时前
网络安全风险评估报告书模版(Word)
运维·数据库·微服务·制造·需求分析
ONETHING_CLOUD_23 小时前
设备存储空间不足怎么办?
数据库·电脑·备份·数据存储·网盘·存储空间·数码知识
用户6279947182623 小时前
南大通用GBase 8a gn层物理存储结构介绍
数据库