oracle中trigger的使用

本文详细介绍Oracle数据库中触发器的创建语法、使用要点及限制条件,并通过实例演示触发器的定义与错误处理方法。

理论知识:

Basic Trigger Syntax
Below is the syntax for creating a trigger in Oracle (which differs slightly from standard SQL syntax):
CREATE [OR REPLACE] TRIGGER <trigger_name>

{BEFORE|AFTER} {INSERT|DELETE|UPDATE} ON <table_name>

[REFERENCING [NEW AS <new_row_name>] [OLD AS <old_row_name>]]

[FOR EACH ROW [WHEN (<trigger_condition>)]]

<trigger_body>
Some important points to note:
You can create only BEFORE and AFTER triggers for tables. (INSTEAD OF triggers are only available for views; typically they are used to implement view updates.)
You may specify up to three triggering events using the keyword OR. Furthermore, UPDATE can be optionally followed by the keyword OF and a list of attribute(s) in <table_name>. If present, the OF clause defines the event to be only an update of the attribute(s) listed after OF. Here are some examples:
... INSERT ON R ...

... INSERT OR DELETE OR UPDATE ON R ...

... UPDATE OF A, B OR INSERT ON R ...
If FOR EACH ROW option is specified, the trigger is row-level; otherwise, the trigger is statement-level.
Only for row-level triggers:
The special variables NEW and OLD are available to refer to new and old tuples respectively. Note: In the trigger body, NEW and OLD must be preceded by a colon (":"), but in the WHEN clause, they do not have a preceding colon! See example below.
The REFERENCING clause can be used to assign aliases to the variables NEW and OLD.
A trigger restriction can be specified in the WHEN clause, enclosed by parentheses. The trigger restriction is a SQL condition that must be satisfied in order for Oracle to fire the trigger. This condition cannot contain subqueries. Without the WHEN clause, the trigger is fired for each row.
<trigger_body> is a PL/SQL block, rather than sequence of SQL statements. Oracle has placed certain restrictions on what you can do in <trigger_body>, in order to avoid situations where one trigger performs an action that triggers a second trigger, which then triggers a third, and so on, which could potentially create an infinite loop. The restrictions on <trigger_body> include:
You cannot modify the same relation whose modification is the event triggering the trigger.
You cannot modify a relation connected to the triggering relation by another constraint such as a foreign-key constraint.

--------------------------------------------------------------------------
Trigger Example
We illustrate Oracle's syntax for creating a trigger through an example based on the following two tables:
CREATE TABLE T4 (a INTEGER, b CHAR(10));

CREATE TABLE T5 (c CHAR(10), d INTEGER);
We create a trigger that may insert a tuple into T5 when a tuple is inserted into T4. Specifically, the trigger checks whether the new tuple has a first component 10 or less, and if so inserts the reverse tuple into T5:
CREATE TRIGGER trig1
AFTER INSERT ON T4
REFERENCING NEW AS newRow
FOR EACH ROW
WHEN (newRow.a <= 10)
BEGIN
INSERT INTO T5 VALUES(:newRow.b, :newRow.a);
END trig1;
.
run;
Notice that we end the CREATE TRIGGER statement with a dot and run, as for all PL/SQL statements in general. Running the CREATE TRIGGER statement only creates the trigger; it does not execute the trigger. Only a triggering event, such as an insertion into T4 in this example, causes the trigger to execute.

--------------------------------------------------------------------------
Displaying Trigger Definition Errors
As for PL/SQL procedures, if you get a message
Warning: Trigger created with compilation errors.
you can see the error messages by typing
show errors trigger <trigger_name>;
Alternatively, you can type, SHO ERR (short for SHOW ERRORS) to see the most recent compilation error. Note that the reported line numbers where the errors occur are not accurate.

--------------------------------------------------------------------------
Viewing Defined Triggers
To view a list of all defined triggers, use:
select trigger_name from user_triggers;

For more details on a particular trigger:

select trigger_type, triggering_event, table_name, referencing_names, trigger_body
from user_triggers
where trigger_name = '<trigger_name>';

--------------------------------------------------------------------------
Dropping Triggers
To drop a trigger:
drop trigger <trigger_name>;

--------------------------------------------------------------------------
Disabling Triggers
To disable or enable a trigger:
alter trigger <trigger_name> {disable|enable};


--------------------------------------------------------------------------
Aborting Triggers with Error
Triggers can often be used to enforce contraints. The WHEN clause or body of the trigger can check for the violation of certain conditions and signal an error accordingly using the Oracle built-in function RAISE_APPLICATION_ERROR. The action that activated the trigger (insert, update, or delete) would be aborted. For example, the following trigger enforces the constraint Person.age >= 0:
create table Person (age int);

CREATE TRIGGER PersonCheckAge
AFTER INSERT OR UPDATE OF age ON Person
FOR EACH ROW
BEGIN
IF (:new.age < 0) THEN
RAISE_APPLICATION_ERROR(-20000, 'no negative age allowed');
END IF;
END;
.
RUN;

If we attempted to execute the insertion:

insert into Person values (-3);

we would get the error message:

ERROR at line 1:
ORA-20000: no negative age allowed
ORA-06512: at "MYNAME.PERSONCHECKAGE", line 3
ORA-04088: error during execution of trigger 'MYNAME.PERSONCHECKAGE'

and nothing would be inserted. In general, the effects of both the trigger and the triggering statement are rolled back.


--------------------------------------------------------------------------
Mutating Table Errors
Sometimes you may find that Oracle reports a "mutating table error" when your trigger executes. This happens when the trigger is querying or modifying a "mutating table", which is either the table whose modification activated the trigger, or a table that might need to be updated because of a foreign key constraint with a CASCADE policy. To avoid mutating table errors:
A row-level trigger must not query or modify a mutating table. (Of course, NEW and OLD still can be accessed by the trigger.)
A statement-level trigger must not query or modify a mutating table if the trigger is fired as the result of a CASCADE delete.


--------------------------------------------------------------------------
例子1
create or replace trigger TR_AAI01
before delete or update or insert on AAI01
for each row

declare
-- local variables here
number_seq number;
number_rowid number;
begin
if updating then
select seq_tradenum.nextval into number_seq from dual;
:new.EBZ008 :=number_seq;
end if;
if deleting then
insert into EBZ08(EBZ027,AAC000,EBZ008,EBZ009) values ('AAI01',:old.AAI000,:old.EBZ008,:old.EBZ009);
end if;
if inserting then
select seq_rowid.nextval into number_rowid from dual;
select seq_tradenum.nextval into number_seq from dual;
:new.EBZ008 :=number_seq;
:new.EBZ009 := to_char(number_rowid);
end if;
end TR_AAI01;

那么如何截获触发触发起的sql语句呢?itpub上 ryuxy 是这样处理的(原文http://www.itpub.net/701184.html )。
CREATE OR REPLACE TRIGGER TRG_LOG_SQL
BEFORE INSERT
ON MYTABLE
DECLARE
n NUMBER;
stmt varchar2(4000);
sql_text ora_name_list_t;
BEGIN
n := ora_sql_txt(sql_text);
FOR i IN 1..n LOOP
stmt := stmt || sql_text(i);
END LOOP;

INSERT INTO DDL_LOG(DDL_TIME, DDL_USER, DDL_HOST, DDL_IP, DDL_SQL)
VALUES(SYSDATE,USER,SYS_CONTEXT('USERENV','HOST'), SYS_CONTEXT('USERENV','IP_ADDRESS'),stmt);

EXCEPTION
WHEN OTHERS THEN
RAISE;-- Consider logging the error and then re-raise
END ;

<think>好的,我现在需要解决用户的问题:如何用SQL语句从Oracle数据库中导出触发器的定义或内容。首先,我得回忆一下Oracle中如何获取数据库对象的定义。用户提到了触发器,可能需要查询数据字典视图。Oracle的数据字典视图有很多,比如USER_SOURCE、ALL_SOURCE、DBA_SOURCE,这些视图存储了存储过程、函数、触发器等的源代码。但触发器可能存储在这里吗?或者有没有专门的视图?可能需要确认一下。另外,用户希望用SQL语句导出,而不是使用工具如SQL Developer或EXP/EXPDP。所以需要直接通过SELECT语句查询出来。 我记得有一个视图叫做USER_TRIGGERS,它包含了触发器的元数据,比如触发条件、事件等,但可能不包含完整的定义。而完整的DDL可能需要使用DBMS_METADATA包。比如,使用DBMS_METADATA.GET_DDL函数来获取对象的定义。语法大概是DBMS_METADATA.GET_DDL('TRIGGER','触发器名','用户名')。这样可以得到创建触发器的SQL语句。 那用户的问题是如何导出,所以可能需要结合这两个方法。首先通过查询USER_TRIGGERS获取所有触发器的名称,然后使用DBMS_METADATA获取每个触发器的DDL。需要注意权限问题,用户是否有权限访问这些数据字典视图和DBMS_METADATA包。普通用户可能需要被授予权限才能使用DBMS_METADATA。另外,用户提到的是导出触发器的定义,可能包括其源代码。所以需要确保查询的结果包含完整的创建语句。可能还需要处理多个触发器的情况,比如使用循环或者批量生成。例如,用SQL生成一组SELECTDBMS_METADATA.GET_DDL(...)语句,或者编写一个脚本。另外,用户之前的引用中提到过使用EXP或EXPDP进行逻辑备份,其中包含触发器。但用户明确要求用SQL语句,而不是数据泵工具。所以需要排除这些方法,专注于纯SQL的方式。 可能的步骤是:1.查询USER_TRIGGERS或ALL_TRIGGERS获取触发器列表。2.使用DBMS_METADATA.GET_DDL获取每个触发器的DDL语句。 3.将结果输出,比如保存为文本文件或直接在SQL客户端中显示。 需要注意,DBMS_METADATA返回的CLOB类型可能需要处理,比如设置LONG类型的输出,或者在SQL*Plus中使用SET LONG10000之类的命令,确保完整显示。另外,可能需要过滤掉系统触发器或只关注用户自己的触发器。例如,使用USER_TRIGGERS而不是DBA_TRIGGERS,除非用户有DBA权限。 还有,如果触发器名称有大写或小写的问题,可能需要正确的引号处理。比如,触发器名如果是大小写敏感的,需要用双引号括起来。总结,用户需要的是通过SQL查询获取触发器的创建语句,而正确的方法是使用DBMS_METADATA包。因此,回答应该包括查询数据字典视图和使用DBMS_METADATA.GET_DDL函数的示例。</think>### 使用SQL语句导出Oracle触发器的定义 #### 方法一:通过数据字典视图 `USER_TRIGGERS` 查询基本信息 ```sql SELECT TRIGGER_NAME, TRIGGER_TYPE, TRIGGERING_EVENT, TABLE_NAME, STATUS FROM USER_TRIGGERS; ``` 此语句可列出当前用户下的触发器名称、类型、触发事件、关联表和状态[^4]。 --- #### 方法二:使用 `DBMS_METADATA` 导出完整DDL **步骤1:查询所有触发器名称** ```sql SELECT TRIGGER_NAME FROM USER_TRIGGERS; ``` **步骤2:导出指定触发器的完整定义** ```sql SELECT DBMS_METADATA.GET_DDL('TRIGGER', '触发器名称', '所属用户') FROM DUAL; ``` 例如导出用户 `HR` 下的触发器 `EMPLOYEE_AUDIT`: ```sql SELECT DBMS_METADATA.GET_DDL('TRIGGER', 'EMPLOYEE_AUDIT', 'HR') FROM DUAL; ``` **步骤3:批量导出所有触发器** ```sql SELECT DBMS_METADATA.GET_DDL('TRIGGER', TRIGGER_NAME) FROM USER_TRIGGERS; ``` --- #### 注意事项 1. **权限要求**:需拥有 `SELECT` 权限访问 `USER_TRIGGERS` 视图,且能执行 `DBMS_METADATA` 包。 2. **输出格式**:若在SQL*Plus中使用,需设置参数确保完整显示: ```sql SET LONG 10000 SET PAGESIZE 0 ``` 3. **大小写敏感**:若触发器名称包含特殊字符或大小写,需用双引号包裹名称。 --- #### 示例输出 ```sql CREATE OR REPLACE TRIGGER "HR"."EMPLOYEE_AUDIT" BEFORE INSERT OR UPDATE ON EMPLOYEES FOR EACH ROW BEGIN -- 触发器逻辑 END; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值