详细说明直接参考官方手册,我们这里只看操作示例。
1 时间触发器
时间触发器是一种特殊的事件触发器。时间触发器的特点是用户可以定义在任何时间点、 时间区域、每隔多长时间等等的方式来激发触发器,而不是通过数据库中的某些操作包括DML、DDL 操作等来激发,它的最小时间精度为分钟。
时间触发器的创建语法如下:
CREATE [OR REPLACE] TRIGGER 触发器名 WITH ENCRYPTION
AFTER TIMER ON DATABASE
{时间定义语句}
BEGIN
执行语句
END;
示例1:每个月的第 28 天,从早上 9 点开始到晚上 18 点之间,每隔一分钟就打印一个字符串―Hello World。
CREATE OR REPLACE TRIGGER timer1
AFTER TIMER ON DATABASE
FOR EACH 1 MONTH DAY 28
FROM TIME '09:00' TO TIME '18:00' FOR EACH 1 MINUTE
DECLARE
str VARCHAR;
BEGIN
PRINT 'HELLO WORLD';
END;
/
示例2:每隔一分钟输出一行―HELLO WORLD:
CREATE OR REPLACE TRIGGER timer2
AFTER TIMER on database
for each 1 day for each 1 minute
BEGIN
print 'HELLO WORLD';
END;
/
2 表级触发器
2.1 表级触发器语法
CREATE [OR REPLACE] TRIGGER 触发器名[WITH ENCRYPTION]
BEFORE|AFTER|INSTEAD OF
DELETE|INSERT|UPDATE [OF 列名]
ON 表名
[FOR EACH ROW [WHEN 条件]]
BEGIN
DMSQL 程序语句
END;
表级触发器的触发动作有三种:INSERT、DELETE 和 UPDATE 操作。其中 UPDATE 触发器会依赖于所修改的列,在定义中可通过 UPDATE OF <触发列清单>的形式来指定所修改的列,<触发列清单>指定的字段数不能超过 128 个。
触发级别:为行级(FOR EACH ROW)和语句级(FOR EACH STATEMENT )。例如将500行记录插入表TABLE_1中的 INSERT 语句,语句级 INSERT 触发器只执行一次。行级触发器会触发500次。FOR EACH STATEMENT 子句创建的,该子句可缺省。
所以表级触发器支持的类型有:
BEFORE INSERT: 在一个 INSERT 处理前激发一次
AFTER INSERT:在一个 INSERT 处理后激发一次
BEFORE DELETE:在一个 DELETE 处理前激发一次
AFTER DELETE:在一个 DELETE 处理后激发一次
BEFORE UPDATE:在一个 UPDATE 处理前激发一次
AFTER UPDATE:在一个 UPDATE 处理后激发一次
BEFORE INSERT FOR EACH ROW :每条新记录插入前激发
AFTER INSERT FOR EACH ROW : 每条新记录插入后激发
BEFORE DELETE FOR EACH ROW : 每条记录被删除前激发
AFTER DELETE FOR EACH ROW : 每条记录被删除后激发
BEFORE UPDATE FOR EACH ROW : 每条记录被修改前激发
AFTER UPDATE FOR EACH ROW : 每条记录被修改后激发
2.2 示例 1 : BEFORE: 在插入一条记录前,将记录中 COL1 列的值加 1
SQL> create table t1(id int,name varchar(50));
操作已执行
已用时间: 23.943(毫秒). 执行号:8403.
SQL> CREATE OR REPLACE TRIGGER TRG_INS_BEFORE
2 BEFORE INSERT ON SYSDBA.t1
3 FOR EACH ROW
4 BEGIN
5 :NEW.ID:=:NEW.ID+1;
6 END;
7 /
操作已执行
已用时间: 24.357(毫秒). 执行号:8404.
SQL> insert into t1 values(1,'cndba');
影响行数 1
已用时间: 1.208(毫秒). 执行号:8405.
SQL> select * from t1;
行号 ID NAME
---------- ----------- -----
1 2 cndba
已用时间: 0.985(毫秒). 执行号:8406.
SQL>
2.3 示例2:AFTER: 在插入一条记录后,将插入的值以及操作类型记录到用于审计的表 T_TEMP 中。
SQL> CREATE TABLE T_TEMP(C1 INT,C2 CHAR(20));
操作已执行
已用时间: 11.429(毫秒). 执行号:8408.
SQL> CREATE OR REPLACE TRIGGER TRG_INS_AFTER
2 AFTER INSERT ON SYSDBA.t1
3 FOR EACH ROW
4 BEGIN
5 INSERT INTO SYSDBA.T_TEMP VALUES(:NEW.ID, 'INSERT ON T1');
6 END;
7 /
操作已执行
已用时间: 14.753(毫秒). 执行号:8409.
SQL> insert into t1 values(1,'cndba');
影响行数 1
已用时间: 1.347(毫秒). 执行号:8410.
SQL> select * from t_temp;
行号 C1 C2
---------- ----------- --------------------
1 2 INSERT ON T1
已用时间: 0.799(毫秒). 执行号:8411.
SQL>
2.4 示例3:INSTEAD OF 触发器
INSTEAD OF 只允许建立在视图上,并且只支持行级触发。
当执行 UPDATE 动作时候,触发触发器。将原动作替换成触发器里的动作。
SQL> create view v1 as select * from SYSDBA.t1;
操作已执行
已用时间: 18.211(毫秒). 执行号:8413.
SQL> CREATE OR REPLACE TRIGGER tri1
2 INSTEAD OF UPDATE ON SYSDBA.v1
3 BEGIN
4 insert into t1 values(100,'https://www.cndba.cn');
5 END;
6 /
操作已执行
已用时间: 16.429(毫秒). 执行号:8414.
SQL> select * from v1;
行号 ID NAME
---------- ----------- -----
1 2 cndba
2 2 cndba
已用时间: 1.293(毫秒). 执行号:8415.
SQL> update v1 set id=100;
影响行数 2
已用时间: 1.572(毫秒). 执行号:8416.
SQL> select * from v1;
行号 ID NAME
---------- ----------- --------------------
1 2 cndba
2 2 cndba
3 101 https://www.cndba.cn
4 101 https://www.cndba.cn
已用时间: 0.406(毫秒). 执行号:8417.
SQL> select * from t1;
行号 ID NAME
---------- ----------- --------------------
1 2 cndba
2 2 cndba
3 101 https://www.cndba.cn
4 101 https://www.cndba.cn
已用时间: 0.906(毫秒). 执行号:8418.
SQL>
由上面的查询结果可以看出。更新操作并没有成功,而是被触发器中的替换动作替换了。
2.5 示例4:引用变量(:NEW,:OLD) 使用
下例中触发器使用了:OLD 引用变量。该触发器是一个 UPDATE 前触发器,其目的是做更新操作时不论是否更新表中某列的值,该列的值保持原值不变。
SQL> create table t2 as select * from t1;
操作已执行
已用时间: 21.296(毫秒). 执行号:8419.
SQL>
SQL> CREATE OR REPLACE TRIGGER trit2
2 BEFORE UPDATE ON SYSDBA.t2
3 FOR EACH ROW
4 BEGIN
5 :new.id:=:old.id;
6 END;
7 /
操作已执行
已用时间: 29.023(毫秒). 执行号:8420.
SQL>
当执行一个 UPDATE 语句时,触发器都将自动保持原来的ID值不变。
SQL> select * from t2;
行号 ID NAME
---------- ----------- --------------------
1 2 cndba
2 2 cndba
3 101 https://www.cndba.cn
4 101 https://www.cndba.cn
已用时间: 1.170(毫秒). 执行号:8421.
SQL> update t2 set id=999 where id=2;
影响行数 2
已用时间: 1.438(毫秒). 执行号:8422.
SQL> select * from t2;
行号 ID NAME
---------- ----------- --------------------
1 2 cndba
2 2 cndba
3 101 https://www.cndba.cn
4 101 https://www.cndba.cn
已用时间: 0.422(毫秒). 执行号:8423.
SQL>
当然,可以改变原来的值,对数据进行处理,比如我们这里讲id 放大2倍再更新:
SQL> CREATE OR REPLACE TRIGGER trit2
2 BEFORE UPDATE ON SYSDBA.t2
3 FOR EACH ROW
4 BEGIN
5 :new.id:=:new.id*2;
6 END;
7 /
操作已执行
已用时间: 19.350(毫秒). 执行号:8424.
SQL> select * from t2;
行号 ID NAME
---------- ----------- --------------------
1 2 cndba
2 2 cndba
3 101 https://www.cndba.cn
4 101 https://www.cndba.cn
已用时间: 1.214(毫秒). 执行号:8425.
SQL> update t2 set id=100 where id=2;
影响行数 2
已用时间: 1.501(毫秒). 执行号:8426.
SQL> select * from t2;
行号 ID NAME
---------- ----------- --------------------
1 200 cndba
2 200 cndba
3 101 https://www.cndba.cn
4 101 https://www.cndba.cn
已用时间: 0.412(毫秒). 执行号:8427.
SQL>
上面没有指定列,也可以在update 指定具体列:
SQL> CREATE OR REPLACE TRIGGER trit2
2 BEFORE UPDATE of id,name ON SYSDBA.t2
3 FOR EACH ROW
4 BEGIN
5 :new.id:=:old.id;
6 END;
7 /
操作已执行
已用时间: 11.697(毫秒). 执行号:8430.
SQL>
2.6 示例5:触发器谓词
触发事件可以是多个数据操作的组合,即一个触发器可能既是 INSERT 触发器,又DELETE 或 UPDATE 触发器。当一个触发器可以为多个 DML 语句触发时,在这种触发器体内部可以使用三个谓词:INSERTING、DELETING 和 UPDATING 来确定当前执行的是何种操作。
CREATE OR REPLACE TRIGGER LogChanges
AFTER INSERT OR DELETE OR UPDATE ON OTHER.READER
FOR EACH ROW
DECLARE
v_ChangeType CHAR(1);
BEGIN
/* I‘表示 INSERT 操作,‘D‘表示 DELETE 操作,‘U‘表示 UPDATE 操作 */
IF INSERTING THEN
v_ChangeType := 'I';
ELSIF UPDATING THEN
v_ChangeType := 'U';
ELSE
v_ChangeType := 'D';
END IF;
/* 记录对 Reader 做的所有修改到表 ReaderAudit 中,包括修改人和修改时间 */
INSERT INTO OTHER.READERAUDIT
VALUES
(v_ChangeType, USER, SYSDATE,
:old.reader_id, :old.name, :old.age, :old.gender, :old.major,
:new.reader_id, :new.name, :new.age, :new.gender, :new.major);
END;
/
3 事件触发器
3.1 事件触发器说明
可以在数据库或模式上创建事件触发器。
DDL 事件: 包括数据库和模式上的 DDL 操作;支持的DDL 事件包括:DDL 或 CREATE、ALTER、 DROP、GRANT、REVOKE、TRUNCATE、COMMENT等。
系统事件: 包括数据库上的除 DDL 操作以外系统事件;以上事件可以有多个,用 OR 列出。支持的系统事件包括:LOGIN/LOGON、LOGOUT/LOGOFF、SERERR、BACKUP DATABASE、 RESTORE DATABASE、AUDIT、NOAUDIT、TIMER、STARTUP、SHUTDOWN;
触发事件按照兼容性可以分为以下几个集合:{CREATE,ALTER,DROP,TRUNCATE,COMMENT }、{ GRANT, REVOKE }、{ LOGIN/LOGON, LOGOUT/LOGOFF }、{ SERERR }、{ BACKUP DATABASE, RESTORE DATABASE }、{AUDIT, NOAUDIT}、{TIMER}、{ STARTUP, SHUTDOWN }。
简单的说,同一个括号里的事件是相互冲突的,不能同时出现。
触发时间分为 BEFORE 和 AFTER:
- 所有 DDL 事件触发器都可以设置 BEFORE 或 AFTER 的触发时机,
- 系统事件中 LOGOUT 和 SHUTDOWN 仅能设置为 BEFORE,而其它则只能设置为 AFTER。
模式级触发器不能是 LOGIN/LOGON、LOGOUT/LOGOFF、SERERR、BACKUP DATABASE、RESTORE DATABASE、STARTUP 和 SHUTDOWN 事件触发器。
对于事件触发器,所有的事件信息都通过伪变量 :EVENTINFO 来取得。 不通操作变量值会有些出入,具体查看官方手册。
3.2 DDL 触发事件使用示例
创建基表:
SQL> CREATE TABLE T01_TRI_10000(OBJECTTYPE VARCHAR(500),OBJECTNAME VARCHAR(500), SCHEMANAME VARCHAR(500),DATABASENAME VARCHAR(500),OPUSER VARCHAR(500), OPTIME VARCHAR(500));
操作已执行
已用时间: 21.509(毫秒). 执行号:8431.
SQL> CREATE TABLE T02_TRI_10000 (C1 INT,C2 VARCHAR(50));
操作已执行
已用时间: 19.458(毫秒). 执行号:8432.
SQL> INSERT INTO T02_TRI_10000 VALUES (1,'https://www.cndba.cn');
影响行数 1
已用时间: 0.915(毫秒). 执行号:8433.
创建事件触发器:
SQL> CREATE TRIGGER TRI01_TRI_10000
2 BEFORE CREATE ON DATABASE
3 BEGIN
4 INSERT INTO T01_TRI_10000 VALUES(:EVENTINFO.OBJECTTYPE,:EVENTINFO.OBJECTNAME,:EVENTINFO.SCHEMANAME,:EVENTINFO.DATABASENAME,:EVENTINFO.OPUSER, :EVENTINFO.OPTIME);
5 END;
6 /
操作已执行
已用时间: 34.589(毫秒). 执行号:8434.
SQL>
创建DDL 测试数据:
SQL> CREATE USER L01_TRI_10000 IDENTIFIED BY L01_TRI_10000;
操作已执行
已用时间: 24.593(毫秒). 执行号:8435.
SQL> CREATE TABLE T03_TRI_10000(C1 INT);
操作已执行
已用时间: 19.170(毫秒). 执行号:8436.
SQL> CREATE VIEW V01_TRI_10000 AS SELECT * FROM T01_TRI_10000;
操作已执行
已用时间: 24.002(毫秒). 执行号:8437.
SQL> CREATE INDEX I01_TRI_10000 ON T01_TRI_10000(OBJECTTYPE);
操作已执行
已用时间: 24.276(毫秒). 执行号:8438.
SQL> CREATE OR REPLACE PROCEDURE P01_TRI_10000 AS BEGIN SELECT * FROM
2 T02_TRI_10000; END;
3 /
操作已执行
已用时间: 26.278(毫秒). 执行号:8439.
SQL> CREATE FUNCTION F01_TRI_10000 RETURN VARCHAR(30) AS A1 VARCHAR(30); BEGIN
2 SELECT C2 INTO A1 FROM T02_TRI_10000 WHERE C1=1; PRINT A1; RETURN A1; END;
3 /
操作已执行
已用时间: 27.806(毫秒). 执行号:8440.
SQL> CREATE ROLE R01_TRI_10000;
操作已执行
已用时间: 6.706(毫秒). 执行号:8441.
SQL> CREATE SEQUENCE S01_TRI_10000 INCREMENT BY 10;
操作已执行
已用时间: 13.231(毫秒). 执行号:8442.
SQL> CREATE TRIGGER TRI02_TRI_10000 AFTER CREATE ON DATABASE BEGIN PRINT
2 'SUCCESS';END;
3 /
操作已执行
已用时间: 17.455(毫秒). 执行号:8443.
SQL>
验证触发器数据:
SQL> SELECT OBJECTTYPE, OBJECTNAME, SCHEMANAME, DATABASENAME, OPUSER FROM T01_TRI_10000;
行号 OBJECTTYPE OBJECTNAME SCHEMANAME DATABASENAME OPUSER
---------- ---------- --------------- ---------- ------------ ------
1 USER L01_TRI_10000 NULL dave SYSDBA
2 TABLE T03_TRI_10000 SYSDBA dave SYSDBA
3 VIEW V01_TRI_10000 SYSDBA dave SYSDBA
4 INDEX I01_TRI_10000 SYSDBA dave SYSDBA
5 PROCEDURE P01_TRI_10000 SYSDBA dave SYSDBA
6 FUNCTION F01_TRI_10000 SYSDBA dave SYSDBA
7 ROLE R01_TRI_10000 NULL dave SYSDBA
8 SEQUENCE S01_TRI_10000 SYSDBA dave SYSDBA
9 TRIGGER TRI02_TRI_10000 SYSDBA dave SYSDBA
9 rows got
已用时间: 1.224(毫秒). 执行号:8444.
3.3 系统触发事件使用示例
只要一登录,服务器就会打印出 SUCCESS
SQL> create or replace trigger test_trigger
2 after LOGIN on database
3 begin
4 print'SUCCESS';
5 end;
6 /
SUCCESS
操作已执行
已用时间: 16.033(毫秒). 执行号:8445.
SQL>
4其他操作
4.1 编译触发器
语法:
ALTER TRIGGER [<模式名>.]<触发器名> COMPILE [DEBUG];
查看触发器状态:
SQL> select OWNER,OBJECT_NAME,STATUS from dba_objects where OBJECT_TYPE='TRIGGER';
行号 OWNER OBJECT_NAME STATUS
---------- ------ ----------------------- ------
1 SYSDBA DMHS_DDL_TRIGGER_AFTER VALID
2 SYSDBA DMHS_DDL_TRIGGER_BEFORE VALID
3 SYSDBA DMHS_DDL_TRIGGER_GRANT VALID
4 SYSDBA DMHS_DDL_TRIGGER_REVOKE VALID
5 SYSDBA TEST_TRIGGER VALID
6 SYSDBA TIMER1 VALID
7 SYSDBA TIMER2 VALID
8 SYSDBA TRG_INS_AFTER VALID
9 SYSDBA TRG_INS_BEFORE VALID
10 SYSDBA TRI01_TRI_10000 VALID
11 SYSDBA TRI02_TRI_10000 VALID
12 SYSDBA TRI1 VALID
13 SYSDBA TRIT2 VALID
13 rows got
已用时间: 13.144(毫秒). 执行号:8450.
当触发器无效时,可以重新编译:
SQL> ALTER TRIGGER SYSDBA.TRI1 COMPILE;
操作已执行
已用时间: 12.273(毫秒). 执行号:8451.
SQL>
4.2 禁止和允许触发器
语法:
ALTER TRIGGER [<模式名>.]<触发器名>
;
SQL> ALTER TRIGGER SYSDBA.TRI1 DISABLE;
SQL> select OWNER,TRIGGER_NAME,STATUS from dba_triggers;
行号 OWNER TRIGGER_NAME STATUS
---------- ------ ----------------------- ------
1 SYSDBA DMHS_DDL_TRIGGER_AFTER Y
2 SYSDBA DMHS_DDL_TRIGGER_BEFORE Y
3 SYSDBA DMHS_DDL_TRIGGER_GRANT Y
4 SYSDBA DMHS_DDL_TRIGGER_REVOKE Y
5 SYSDBA TEST_TRIGGER Y
6 SYSDBA TIMER1 Y
7 SYSDBA TIMER2 Y
8 SYSDBA TRG_INS_AFTER Y
9 SYSDBA TRG_INS_BEFORE Y
10 SYSDBA TRI01_TRI_10000 Y
11 SYSDBA TRI02_TRI_10000 Y
12 SYSDBA TRI1 N
13 SYSDBA TRIT2 Y
13 rows got
已用时间: 7.533(毫秒). 执行号:68411.
SQL>
事件触发器也是一样操作:
SQL> ALTER TRIGGER SYSDBA.test_trigger DISABLE;
操作已执行
已用时间: 7.033(毫秒). 执行号:68412.
SQL> select OWNER,TRIGGER_NAME,STATUS from dba_triggers;
行号 OWNER TRIGGER_NAME STATUS
---------- ------ ----------------------- ------
1 SYSDBA DMHS_DDL_TRIGGER_AFTER Y
2 SYSDBA DMHS_DDL_TRIGGER_BEFORE Y
3 SYSDBA DMHS_DDL_TRIGGER_GRANT Y
4 SYSDBA DMHS_DDL_TRIGGER_REVOKE Y
5 SYSDBA TEST_TRIGGER N
6 SYSDBA TIMER1 Y
7 SYSDBA TIMER2 Y
8 SYSDBA TRG_INS_AFTER Y
9 SYSDBA TRG_INS_BEFORE Y
10 SYSDBA TRI01_TRI_10000 Y
11 SYSDBA TRI02_TRI_10000 Y
12 SYSDBA TRI1 N
13 SYSDBA TRIT2 Y
13 rows got
已用时间: 4.148(毫秒). 执行号:68413.
SQL>
4.3 删除触发器
语法:
DROP TRIGGER [IF EXISTS] [<模式名>.]<触发器名>;
SQL> DROP TRIGGER SYSDBA.TRI1;
操作已执行
已用时间: 24.707(毫秒). 执行号:68414.
SQL>
5 官方手册示例
5.1 引用完整性维护
删除被引用表中的数据时,级联删除引用表中引用该数据的记录;
更新被引用表中的数据时,更新引用表中引用该数据的记录的相应字段。
下例中,表 OTHER.DEPTTAB 为被引用表,其主关键字为 Deptno;表 OTHER.EMPTAB 为引用表。其结构如下:
CREATE OR REPLACE TRIGGER Dept_del_upd_cascade
AFTER DELETE OR UPDATE ON OTHER.DEPTTAB FOR EACH ROW
BEGIN
IF DELETING THEN
DELETE FROM OTHER.EMPTAB WHERE Deptno = :old.Deptno;
ELSE
UPDATE OTHER.EMPTAB SET Deptno = :new.Deptno WHERE Deptno = :old.Deptno;
END IF;
END;
5.2 CHECK 规则检查
增加新员工或者调整员工工资时,保证其工资不超过规定的范围,并且涨幅不超过 25%。
该例中,表 OTHER.EMPTAB 记录员工信息;表 OTHER.SALGRADE 记录各个工种的工资范围,其结构如下:
SET SCHEMA OTHER;
CREATE OR REPLACE TRIGGER Salary_check
BEFORE INSERT OR UPDATE ON OTHER.EMPTAB
FOR EACH ROW
DECLARE
Minsal FLOAT;
Maxsal FLOAT;
Salary_out_of_range EXCEPTION FOR -20002;
BEGIN
/* 取该员工所属工种的工资范围 */
SELECT Losal, Hisal INTO Minsal, Maxsal FROM OTHER.SALGRADE WHERE Job_classification = :new.Job;
/* 如果工资超出工资范围,报告异常 */
IF (:new.Sal < Minsal OR :new.Sal > Maxsal) THEN
RAISE Salary_out_of_range;
END IF;
/* 如果工资涨幅超出 25%,报告异常 */
IF UPDATING AND (:new.Sal - :old.Sal)/:old.Sal > 0.25 THEN
RAISE Salary_out_of_range;
END IF;
END;
SET SCHEMA SYSDBA;
5.3 使用触发器保障数据安全性
在复杂的条件下,可以使用触发器来保障数据的安全性。同样,要注意不要用触发器来实现 DM 安全机制已提供的功能。
使用触发器进行安全控制时,应使用语句级 BEFORE 类型的触发器,其优点如下:
1.在执行触发事件之前进行安全检查,可以避免系统在触发语句不能通过安全检查的
情况下做不必要的工作;
2.使用语句级触发器,安全检查只需要对每个触发语句进行一次,而不必对语句影响
的每一行都执行一次。
下面这个例子显示如何用触发器禁止在非工作时间内修改表 OTHER.EMPTAB 中的工资 (Sal)栏。非工作时间包括周末、公司规定的节假日以及下班后的时间。为此,我们用表OTHER.C OMPANYHOLIDAYS 来记录公司规定的节假日。
SET SCHEMA OTHER;
CREATE OR REPLACE TRIGGER Emp_permit_changes
BEFORE INSERT OR DELETE OR UPDATE
ON OTHER.EMPTAB
DECLARE
Dummy INTEGER;
Invalid_Operate_time EXCEPTION FOR -20002;
BEGIN
/* 检查是否周末 */
IF (DAYNAME(Sysdate) = 'Saturday' OR DAYNAME(Sysdate) = 'Sunday')
RAISE Invalid_Operate_time;
END IF;
/* 检查是否节假日 */
SELECT COUNT(*) INTO Dummy FROM OTHER.COMPANYHOLIDAYS WHERE Holiday= Current_date;
IF dummy > 0 THEN
RAISE Invalid_Operate_time;
END IF;
/* 检查是否上班时间 */
IF (EXTRACT(HOUR FROM Current_time) < 8 OR EXTRACT(HOUR FROM Current_time) >= 18) THEN
RAISE Invalid_Operate_time;
END IF;
END;
SET SCHEMA SYSDBA;
5.4 使用触发器生成字段默认值
触发器还经常用来自动生成某些字段的值,这些字段的值有时依赖于本记录中的其他字段的值,有时是为了避免用户直接对这些字段进行修改。这类触发器应该是元组级 BEFORE INSERT 或 UPDATE 触发器。因为:
1.必须在 INSERT 或 UPDATE 操作执行之前生成字段的值;
2.必须为每条元组自动生成一次字段的值。
SET SCHEMA OTHER;
CREATE OR REPLACE TRIGGER Emp_auto_value
BEFORE INSERT
ON OTHER.EMPTAB
FOR EACH ROW
BEGIN
:new.Sal = 999.99;
END;
SET SCHEMA SYSDBA;
版权声明:本文为博主原创文章,未经博主允许不得转载。