原文链接: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技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。