oracle触发器高级教程

【转自】http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7004.htm#i2153503

CREATE TRIGGER

Purpose

Use theCREATETRIGGERstatement to create and enable adatabase trigger, which is:

  • A stored PL/SQL block associated with a table, a schema, or the database or

  • An anonymous PL/SQL block or a call to a procedure implemented in PL/SQL or Java

Oracle Database automatically executes a trigger when specified conditions occur.

When you create a trigger, the database enables it automatically. You can subsequently disable and enable a trigger with theDISABLEandENABLEclause of theALTERTRIGGERorALTERTABLEstatement.

See Also:

Prerequisites

Before a trigger can be created, the userSYSmust run a SQL script commonly calledDBMSSTDX.SQL. The exact name and location of this script depend on your operating system.

  • To create a trigger in your own schema on a table in your own schema or on your own schema (SCHEMA), you must have theCREATETRIGGERsystem privilege.

  • To create a trigger in any schema on a table in any schema, or on another user's schema (schema.SCHEMA), you must have theCREATEANYTRIGGERsystem privilege.

  • In addition to the preceding privileges, to create a trigger onDATABASE, you must have theADMINISTERDATABASETRIGGERsystem privilege.

If the trigger issues SQL statements or calls procedures or functions, then the owner of the trigger must have the privileges necessary to perform these operations. These privileges must be granted directly to the owner rather than acquired through roles.

Syntax

create_trigger::=

oracle触发器高级教程_第1张图片

DML_event_clause::=

oracle触发器高级教程_第2张图片

referencing_clause::=

oracle触发器高级教程_第3张图片

Semantics

OR REPLACE

SpecifyORREPLACEto re-create the trigger if it already exists. Use this clause to change the definition of an existing trigger without first dropping it.

schema

Specify the schema to contain the trigger. If you omitschema, then Oracle Database creates the trigger in your own schema.

trigger

Specify the name of the trigger to be created.

If a trigger produces compilation errors, then it is still created, but it fails on execution. This means it effectively blocks all triggering DML statements until it is disabled, replaced by a version without compilation errors, or dropped. You can see the associated compiler error messages with the SQL*Plus commandSHOWERRORS.

Note:

If you create a trigger on a base table of a materialized view, then you must ensure that the trigger does not fire during a refresh of the materialized view. During refresh, the DBMS_MVIEWprocedure I_AM_A_REFRESHreturns TRUE.

BEFORE

SpecifyBEFOREto cause the database to fire the trigger before executing the triggering event. For row triggers, the trigger is fired before each affected row is changed.

Restrictions on BEFORE TriggersBEFOREtriggers are subject to the following restrictions:

  • You cannot specify aBEFOREtrigger on a view or an object view.

  • You can write to the :NEWvalue but not to the :OLDvalue.

AFTER

SpecifyAFTERto cause the database to fire the trigger after executing the triggering event. For row triggers, the trigger is fired after each affected row is changed.

Restrictions on AFTER TriggersAFTERtriggers are subject to the following restrictions:

  • You cannot specify anAFTERtrigger on a view or an object view.

  • You cannot write either the :OLDor the :NEWvalue.

Note:

When you create a materialized view log for a table, Oracle Database implicitly creates an AFTER ROWtrigger on the table. This trigger inserts a row into the materialized view log whenever an INSERT, UPDATE, or DELETEstatement modifies data in the master table. You cannot control the order in which multiple row triggers fire. Therefore, you should not write triggers intended to affect the content of the materialized view.

See Also:

CREATE MATERIALIZED VIEW LOGfor more information on materialized view logs

INSTEAD OF

SpecifyINSTEADOFto cause Oracle Database to fire the trigger instead of executing the triggering event.INSTEADOFtriggers are valid for DML events on views. They are not valid for DDL or database events.

If a view is inherently updatable and hasINSTEADOFtriggers, then the triggers take preference. In other words, the database fires the triggers instead of performing DML on the view.

If the view belongs to a hierarchy, then the trigger is not inherited by subviews.

Note:

Oracle Database fine-grained access control lets you define row-level security policies on views. These policies enforce specified rules in response to DML operations. If an INSTEAD OFtrigger is also defined on the view, then the database will not enforce the row-level security policies, because the database fires the INSTEAD OFtrigger instead of executing the DML on the view.

INSTEAD OF Triggers

  • INSTEADOFtriggers are valid only for views. You cannot specify anINSTEADOFtrigger on a table.

  • You can read both the :OLDand the :NEWvalue, but you cannot write either the :OLDor the :NEWvalue.

Note:

You can create multiple triggers of the same type ( BEFORE, AFTER, or INSTEAD OF) that fire for the same statement on the same table. The order in which Oracle Database fires these triggers is indeterminate. If your application requires that one trigger be fired before another of the same type for the same statement, then combine these triggers into a single trigger whose trigger action performs the trigger actions of the original triggers in the appropriate order.

DML_event_clause

TheDML_event_clauselets you specify one of three DML statements that can cause the trigger to fire. Oracle Database fires the trigger in the existing user transaction.

You cannot specify theMERGEkeyword in theDML_event_clause. If you want a trigger to fire in relation to aMERGEoperation, you must create triggers on theINSERTandUPDATEoperations to which theMERGEoperation decomposes.

DELETE

SpecifyDELETEif you want the database to fire the trigger whenever aDELETEstatement removes a row from the table or removes an element from a nested table.

INSERT

SpecifyINSERTif you want the database to fire the trigger whenever anINSERTstatement adds a row to a table or adds an element to a nested table.

UPDATE

SpecifyUPDATEif you want the database to fire the trigger whenever anUPDATEstatement changes a value in one of the columns specified afterOF. If you omitOF, then the database fires the trigger whenever anUPDATEstatement changes a value in any column of the table or nested table.

For anUPDATEtrigger, you can specify object type, varray, andREFcolumns afterOFto indicate that the trigger should be fired whenever anUPDATEstatement changes a value in one of the columns. However, you cannot change the values of these columns in the body of the trigger itself.

Note:

Using OCI functions or the DBMS_LOBpackage to update LOB values or LOB attributes of object columns does not cause Oracle Database to fire triggers defined on the table containing the columns or the attributes.

Restrictions on Triggers on UPDATE OperationsTheUPDATEclause is subject to the following restrictions:

  • You cannot specifyUPDATEOFfor anINSTEADOFtrigger. Oracle Database firesINSTEADOFtriggers whenever anUPDATEchanges a value in any column of the view.

  • You cannot specify a nested table or LOB column in theUPDATEOFclause.

See Also:

AS subqueryclause of CREATE VIEWfor a list of constructs that prevent inserts, updates, or deletes on a view

Performing DML operations directly on nested table columns does not cause Oracle Database to fire triggers defined on the table containing the nested table column.

ddl_event

Specify one or more types of DDL statements that can cause the trigger to fire. You can create triggers for these events onDATABASEorSCHEMAunless otherwise noted. You can createBEFOREandAFTERtriggers for these events. Oracle Database fires the trigger in the existing user transaction.

Restriction on Triggers on DDL EventsYou cannot specify as a triggering event any DDL operation performed through a PL/SQL procedure.

The followingddl_eventvalues are valid:

ALTERSpecifyALTERto fire the trigger whenever anALTERstatement modifies a database object in the data dictionary.

Restriction on Triggers on ALTER OperationsThe trigger will not be fired by anALTERDATABASEstatement.

ANALYZESpecifyANALYZEto fire the trigger whenever the database collects or deletes statistics or validates the structure of a database object.

See Also:

ANALYZEfor information on various ways of collecting statistics

ASSOCIATE STATISTICSSpecifyASSOCIATESTATISTICSto fire the trigger whenever the database associates a statistics type with a database object.

AUDITSpecifyAUDITto fire the trigger whenever the database tracks the occurrence of a SQL statement or tracks operations on a schema object.

COMMENTSpecifyCOMMENTto fire the trigger whenever a comment on a database object is added to the data dictionary.

CREATESpecifyCREATEto fire the trigger whenever aCREATEstatement adds a new database object to the data dictionary.

Restriction on Triggers on CREATE OperationsThe trigger will not be fired by aCREATEDATABASEorCREATECONTROLFILEstatement.

DISASSOCIATE STATISTICSSpecifyDISASSOCIATESTATISTICSto fire the trigger whenever the database disassociates a statistics type from a database object.

DROPSpecifyDROPto fire the trigger whenever aDROPstatement removes a database object from the data dictionary.

GRANTSpecifyGRANTto fire the trigger whenever a user grants system privileges or roles or object privileges to another user or to a role.

NOAUDITSpecifyNOAUDITto fire the trigger whenever aNOAUDITstatement instructs the database to stop tracking a SQL statement or operations on a schema object.

RENAMESpecifyRENAMEto fire the trigger whenever aRENAMEstatement changes the name of a database object.

REVOKESpecifyREVOKEto fire the trigger whenever aREVOKEstatement removes system privileges or roles or object privileges from a user or role.

TRUNCATESpecifyTRUNCATEto fire the trigger whenever aTRUNCATEstatement removes the rows from a table or cluster and resets its storage characteristics.

DDLSpecifyDDLto fire the trigger whenever any of the preceding DDL statements is issued.

database_event

Specify one or more particular states of the database that can cause the trigger to fire. You can create triggers for these events onDATABASEorSCHEMAunless otherwise noted. For each of these triggering events, Oracle Database opens an autonomous transaction scope, fires the trigger, and commits any separate transaction (regardless of any existing user transaction).

SERVERERRORSpecifySERVERERRORto fire the trigger whenever a server error message is logged.

The following errors do not cause aSERVERERRORtrigger to fire:

  • ORA-01403: no data found

  • ORA-01422: exact fetch returns more than requested number of rows

  • ORA-01423: error encountered while checking for extra rows in exact fetch

  • ORA-01034: ORACLE not available

  • ORA-04030: out of process memory when trying to allocatestringbytes (string,string)

LOGONSpecifyLOGONto fire the trigger whenever a client application logs onto the database.

LOGOFFSpecifyLOGOFFto fire the trigger whenever a client application logs off the database.

STARTUPSpecifySTARTUPto fire the trigger whenever the database is opened.

SHUTDOWNSpecifySHUTDOWNto fire the trigger whenever an instance of the database is shut down.

SUSPENDSpecifySUSPENDto fire the trigger whenever a server error causes a transaction to be suspended.

DB_ROLE_CHANGEIn a Data Guard configuration, specifyDB_ROLE_CHANGEto fire the trigger whenever a role change occurs from standby to primary or from primary to standby.

Notes:

  • OnlyAFTERtriggers are relevant forLOGON,STARTUP,SERVERERROR,SUSPEND, andDB_ROLE_CHANGE.

  • OnlyBEFOREtriggers are relevant forLOGOFFandSHUTDOWN.

  • AFTERSTARTUPandBEFORESHUTDOWNtriggers apply only toDATABASE.

See Also:

PL/SQL User's Guide and Referencefor more information on autonomous transaction scope

ONtable|view

TheONclause lets you determine the database object on which the trigger is to be created. Specify theschemaandtableorviewname of one of the following on which the trigger is to be created:

  • Table or view

  • Object table or object view

  • A column of nested-table type

If you omitschema, then Oracle Database assumes the table is in your own schema. You can create triggers on index-organized tables.

Restriction on SchemaYou cannot create a trigger on a table in the schemaSYS.

NESTED TABLE Clause

Specify thenested_table_columnof a view upon which the trigger is being defined. Such a trigger will fire only if the DML operates on the elements of the nested table.

Restriction on Triggers on Nested TablesYou can specifyNESTEDTABLEonly forINSTEADOFtriggers.

DATABASE

SpecifyDATABASEto define the trigger on the entire database. The trigger fires whenever any database user initiates the triggering event.

SCHEMA

SpecifySCHEMAto define the trigger on the current schema. The trigger fires whenever any user connected asschemainitiates the triggering event.

referencing_clause

Thereferencing_clauselets you specify correlation names. You can use correlation names in the PL/SQL block andWHENcondition of a row trigger to refer specifically to old and new values of the current row. The default correlation names areOLDandNEW. If your row trigger is associated with a table namedOLDorNEW, use this clause to specify different correlation names to avoid confusion between the table name and the correlation name.

  • If the trigger is defined on a nested table, thenOLDandNEWrefer to the row of the nested table, andPARENTrefers to the current row of the parent table.

  • If the trigger is defined on an object table or view, thenOLDandNEWrefer to object instances.

Restriction on thereferencing_clauseThereferencing_clauseis not valid withINSTEADOFtriggers onCREATEDDL events.

FOR EACH ROW

SpecifyFOREACHROWto designate the trigger as a row trigger. Oracle Database fires a row trigger once for each row that is affected by the triggering statement and meets the optional trigger constraint defined in theWHENcondition.

Except forINSTEADOFtriggers, if you omit this clause, then the trigger is a statement trigger. Oracle Database fires a statement trigger only once when the triggering statement is issued if the optional trigger constraint is met.

INSTEADOFtrigger statements are implicitly activated for each row.

Restriction on Row TriggersThis clause is valid only for DML event triggers, not for DDL or database event triggers.

WHEN Clause

Specify the trigger condition, which is a SQL condition that must be satisfied for the database to fire the trigger. See the syntax description ofconditioninChapter 7, "Conditions". This condition must contain correlation names and cannot contain a query.

TheNEWandOLDkeywords, when specified in theWHENclause, are not considered bind variables, so are not preceded by a colon (:). However, you must precedeNEWandOLDwith a colon in all references other than theWHENclause.

Restrictions on Trigger ConditionsTrigger conditions are subject to the following restrictions:

  • If you specify this clause for a DML event trigger, then you must also specifyFOREACHROW. Oracle Database evaluates this condition for each row affected by the triggering statement.

  • You cannot specify trigger conditions forINSTEADOFtrigger statements.

  • You can reference object columns or their attributes, or varray, nested table, or LOB columns. You cannot invoke PL/SQL functions or methods in the trigger condition.

pl/sql_block

Specify the PL/SQL block that Oracle Database executes to fire the trigger.

The PL/SQL block of a database trigger can contain one of a series of built-in functions in theSYSschema designed solely to extract system event attributes. These functions can be usedonlyin the PL/SQL block of a database trigger.

Restrictions on Trigger ImplementationThe implementation of a trigger is subject to the following restrictions:

  • The PL/SQL block of a trigger cannot contain transaction control SQL statements (COMMIT,ROLLBACK,SAVEPOINT, andSETCONSTRAINT) if the block is executed within the same transaction.

  • You can reference and use LOB columns in the trigger action inside the PL/SQL block. You can modify the :NEWvalues but not the :OLDvalues of LOB columns within the trigger action.

See Also:

call_procedure_statement

Thecall_procedure_statementlets you call a stored procedure rather than specifying the trigger code inline as a PL/SQL block. The syntax of this statement is the same as that forCALL, with the following exceptions:

  • You cannot specify theINTOclause ofCALL, because it applies only to functions.

  • You cannot specify bind variables inexpr.

  • To reference columns of tables on which the trigger is being defined, you must specify :NEWand :OLD.

Examples

Creating a DML Trigger: ExamplesThis example shows the basic syntax for aBEFOREstatement trigger. You would write such a trigger to place restrictions on DML statements issued on a table, for example, when such statements could be issued.

CREATE TRIGGER schema.trigger_name 
    BEFORE 
    DELETE OR INSERT OR UPDATE 
    ON schema.table_name 
       pl/sql_block

Oracle Database fires such a trigger whenever a DML statement affects the table. This trigger is aBEFOREstatement trigger, so the database fires it once before executing the triggering statement.

The next example shows a partialBEFORErow trigger. The PL/SQL block might specify, for example, that an employee's salary must fall within the established salary range for the employee's job:

CREATE TRIGGER hr.salary_check
      BEFORE INSERT OR UPDATE OF salary, job_id ON hr.employees
      FOR EACH ROW
         WHEN (new.job_id <> 'AD_VP')
      pl/sql_block

Oracle Database fires this trigger whenever one of the following statements is issued:

  • AnINSERTstatement that adds rows to theemployeestable

  • AnUPDATEstatement that changes values of thesalaryorjob_idcolumns of theemployeestable

salary_checkis aBEFORErow trigger, so the database fires it before changing each row that is updated by theUPDATEstatement or before adding each row that is inserted by theINSERTstatement.

salary_checkhas a trigger condition that prevents it from checking the salary of the administrative vice president (AD_VP).

Creating a DDL Trigger: ExampleThis example creates anAFTERstatement trigger on any DDL statementCREATE. Such a trigger can be used to audit the creation of new data dictionary objects in your schema.

CREATE TRIGGER audit_db_object AFTER CREATE
   ON SCHEMA
      pl/sql_block

Calling a Procedure in a Trigger Body: ExampleYou could create thesalary_checktrigger described in the preceding example by calling a procedure instead of providing the trigger body in a PL/SQL block. Assume you have defined a procedurecheck_salin thehrschema, which verifies that an employee's salary is in an appropriate range. Then you could create the triggersalary_checkas follows:

CREATE TRIGGER salary_check
   BEFORE INSERT OR UPDATE OF salary, job_id ON employees
   FOR EACH ROW
   WHEN (new.job_id <> 'AD_VP')
   CALL check_sal(:new.job_id, :new.salary, :new.last_name)

The procedurecheck_salcould be implemented in PL/SQL, C, or Java. Also, you can specify :OLDvalues in theCALLclause instead of :NEWvalues.

Creating a Database Event Trigger: ExampleThis example shows the basic syntax for a trigger to log all errors. The hypothetical PL/SQL block does some special processing for a particular error (invalid logon, error number 1017). This trigger is anAFTERstatement trigger, so it is fired after an unsuccessful statement execution, such as unsuccessful logon.

CREATE TRIGGER log_errors AFTER SERVERERROR ON DATABASE 
   BEGIN
      IF (IS_SERVERERROR (1017)) THEN
         <special processing of logon error>
      ELSE
         <log error number>
      END IF;
   END;

Creating an INSTEAD OF Trigger: ExampleIn this example, anoe.order_infoview is created to display information about customers and their orders:

CREATE VIEW order_info AS
   SELECT c.customer_id, c.cust_last_name, c.cust_first_name,
          o.order_id, o.order_date, o.order_status
   FROM customers c, orders o 
   WHERE c.customer_id = o.customer_id;

Normally this view would not be updatable, because the primary key of theorderstable (order_id) is not unique in the result set of the join view. To make this view updatable, create anINSTEADOFtrigger on the view to processINSERTstatements directed to the view. The PL/SQL trigger implementation is shown in italics.

CREATE OR REPLACE TRIGGER order_info_insert
   INSTEAD OF INSERT ON order_info
   DECLARE
     duplicate_info EXCEPTION;
     PRAGMA EXCEPTION_INIT (duplicate_info, -00001);
   BEGIN
     INSERT INTO customers
       (customer_id, cust_last_name, cust_first_name) 
     VALUES (
     :new.customer_id, 
     :new.cust_last_name,
     :new.cust_first_name);
   INSERT INTO orders (order_id, order_date, customer_id)
   VALUES (
     :new.order_id,
     :new.order_date,
     :new.customer_id);
   EXCEPTION
     WHEN duplicate_info THEN
       RAISE_APPLICATION_ERROR (
         num=> -20107,
         msg=> 'Duplicate customer or order ID');
   END order_info_insert;
/

You can now insert into both base tables through the view (as long as allNOTNULLcolumns receive values):

INSERT INTO order_info VALUES
   (999, 'Smith', 'John', 2500, '13-MAR-2001', 0);

Creating a SCHEMA Trigger: ExampleThe following example creates aBEFOREstatement trigger on the sample schemahr. When a user connected ashrattempts to drop a database object, the database fires the trigger before dropping the object:

CREATE OR REPLACE TRIGGER drop_trigger 
   BEFORE DROP ON hr.SCHEMA 
   BEGIN
      RAISE_APPLICATION_ERROR (
         num => -20000,
         msg => 'Cannot drop object');
   END;
/
##############################################
##############################################
####################另  一  篇####################
##############################################
##############################################
【转自】http://heisetoufa.javaeye.com/blog/367314
 
 

oracle 触发器的种类和触发事件,DML触发器,DDL事件触发器,替代触发器,查看触发器,

关键字: oracle 触发器 种类 触发 事件 dml ddl 事件 替代 查看
触发器的种类和触发事件
触发器必须由事件才能触发。触发器的触发事件分可为3类,分别是DML事件、DDL事件和数据库事件。
每类事件包含若干个事件,如下所示。数据库的事件是具体的,在创建触发器时要指明触发的事件。
种 类 关 键 字 含 义
Sql代码
  1. DML事件(3种)INSERT在表或视图中插入数据时触发
  2. UPDATE修改表或视图中的数据时触发
  3. DELETE在删除表或视图中的数据时触发
  4. DDL事件(3种)CREATE在创建新对象时触发
  5. ALTER修改数据库或数据库对象时触发
  6. DROP删除对象时触发
  7. 数据库事件(5种)STARTUP数据打开时触发
  8. SHUTDOWN在使用NORMAL或IMMEDIATE选项关闭数据库时触发
  9. LOGON当用户连接到数据库并建立会话时触发
  10. LOGOFF当一个会话从数据库中断开时触发
  11. SERVERERROR发生服务器错误时触发

触发器的类型可划分为4种:数据操纵语言(DML)触发器、替代(INSTEAD OF)触发器、数据定义语言(DDL)触发器和数据库事件触发器。
各类触发器的作用如下所示。
Sql代码
  1. 种类简称作用
  2. 数据操纵语言触发器DML触发器创建在表上,由DML事件引发的触发器
  3. 替代触发器INSTEADOF触发器创建在视图上,用来替换对视图进行的插入、删除和修改操作
  4. 数据定义语言触发器DDL触发器定义在模式上,触发事件是数据库对象的创建和修改
  5. 数据库事件触发器—定义在整个数据库或模式上,触发事件是数据库事件

DML触发器的要点
DML触发器是定义在表上的触发器,由DML事件引发。编写DML触发器的要素是:
* 确定触发的表,即在其上定义触发器的表。
* 确定触发的事件,DML触发器的触发事件有INSERT、UPDATE和DELETE三种,说明见下。
* 确定触发时间。触发的时间有BEFORE和AFTER两种,分别表示触发动作发生在DML语句执行之前和语句执行之后。
* 确定触发级别,有语句级触发器和行级触发器两种。语句级触发器表示SQL语句只触发一次触发器,行级触发器表示SQL语句影响的每一行都要触发一次。
由于在同一个表上可以定义多个DML触发器,因此触发器本身和引发触发器的SQL语句在执行的顺序上有先后的关系。它们的顺序是:
* 如果存在语句级BEFORE触发器,则先执行一次语句级BEFORE触发器。
* 在SQL语句的执行过程中,如果存在行级BEFORE触发器,则SQL语句在对每一行操作之前,都要先执行一次行级BEFORE触发器,然后才对行进行操作。如果存在行级AFTER触发器,则SQL语句在对每一行操作之后,都要再执行一次行级AFTER触发器。
* 如果存在语句级AFTER触发器,则在SQL语句执行完毕后,要最后执行一次语句级AFTER触发器。
DML触发器还有一些具体的问题,说明如下:
* 如果有多个触发器被定义成为相同时间、相同事件触发,且最后定义的触发器是有效的,则最后定义的触发器被触发,其他触发器不执行。
* 一个触发器可由多个不同的DML操作触发。在触发器中,可用INSERTING、DELETING、UPDATING谓词来区别不同的DML操作。这些谓词可以在IF分支条件语句中作为判断条件来使用。
* 在行级触发器中,用:new 和:old(称为伪记录)来访问数据变更前后的值。但要注意,INSERT语句插入一条新记录,所以没有:old记录,而DELETE语句删除掉一条已经存在的记录,所以没有:new记录。UPDATE语句既有:old记录,也有:new记录,分别代表修改前后的记录。引用具体的某一列的值的方法是:
ld.字段名或:new.字段名
* 触发器体内禁止使用COMMIT、ROLLBACK、SAVEPOINT语句,也禁止直接或间接地调用含有上述语句的存储过程。
定义一个触发器时要考虑上述多种情况,并根据具体的需要来决定触发器的种类。
DML触发器的创建
创建DML触发器需要CREATE TRIGGER系统权限。创建DML触发器的语法如下:
CREATE [OR REPLACE] TRIGGER 触发器名
{BEFORE|AFTER|INSTEAD OF} 触发事件1 [OR 触发事件2...]
ON 表名
WHEN 触发条件
[FOR EACH ROW]
DECLARE
声明部分
BEGIN
主体部分
END;
其中:
OR REPLACE:表示如果存在同名触发器,则覆盖原有同名触发器。
BEFORE、AFTER和INSTEAD OF:说明触发器的类型。
WHEN 触发条件:表示当该条件满足时,触发器才能执行。
触发事件:指INSERT、DELETE或UPDATE事件,事件可以并行出现,中间用OR连接。
对于UPDATE事件,还可以用以下形式表示对某些列的修改会引起触发器的动作:
UPDATE OF 列名1,列名2...
ON 表名:表示为哪一个表创建触发器。
FOR EACH ROW:表示触发器为行级触发器,省略则为语句级触发器。
触发器的创建者或具有DROP ANY TIRGGER系统权限的人才能删除触发器。删除触发器的语法如下:
DROP TIRGGER 触发器名
可以通过命令设置触发器的可用状态,使其暂时关闭或重新打开,即当触发器暂时不用时,可以将其置成无效状态,在使用时重新打开。该命令语法如下:
ALTER TRIGGER 触发器名 {DISABLE|ENABLE}
其中,DISABLE表示使触发器失效,ENABLE表示使触发器生效。
同存储过程类似,触发器可以用SHOW ERRORS 检查编译错误。
行级触发器的应用
在行级触发器中,SQL语句影响的每一行都会触发一次触发器,所以行级触发器往往用在对表的每一行的操作进行控制的场合。若在触发器定义中出现FOR EACH ROW子句,则为语句级触发器。
【训练1】 创建包含插入、删除、修改多种触发事件的触发器DML_LOG,对EMP表的操作进行记录。用INSERTING、DELETING、UPDATING谓词来区别不同的DML操作。
在创建触发器之前,需要先创建事件记录表LOGS,该表用来对操作进行记录。该表的字段含义解释如下:
LOG_ID:操作记录的编号,数值型,它是该表的主键,由序列自动生成。
LOG_TABLE:进行操作的表名,字符型,非空,该表设计成可以由多个触发器共享使用。比如我们可以为dept表创建类似的触发器,同样将操作记录到该表。
LOG_DML:操作的动作,即INSERT、DELETE或UPDATE三种之一。
LOG_KEY_ID:操作时表的主键值,数值型。之所以记录表的主键,是因为主键是表的记录的惟一标识,可以识别是对哪一条记录进行了操作。对于emp表,主键是empno。
LOG_DATE:操作的日期,日期型,取当前的系统时间。
LOG_USER:操作者,字符型,取当时的操作者账户名。比如登录SCOTT账户进行操作,在该字段中,记录账户名为SCOTT。
步骤1:在SQL*Plus中登录STUDENT账户,创建如下的记录表LOGS:
Sql代码
  1. CREATETABLElogs(
  2. LOG_IDNUMBER(10)PRIMARYKEY,
  3. LOG_TABLEVARCHAR2(10)NOTNULL,
  4. LOG_DMLVARCHAR2(10),
  5. LOG_KEY_IDNUMBER(10),
  6. LOG_DATEDATE,
  7. LOG_USERVARCHAR2(15)
  8. );

执行结果:
Sql代码
  1. 表已创建。

步骤2:创建一个LOGS表的主键序列LOGS_ID_SEQ:
Sql代码
  1. CREATESEQUENCElogs_id_squINCREMENTBY1
  2. STARTWITH1MAXVALUE9999999NOCYCLENOCACHE;

执行结果:
Sql代码
  1. 序列已创建。

步骤3:创建和编译以下触发器:
Sql代码
  1. CREATEORREPLACETRIGGERDML_LOG
  2. BEFORE--触发时间为操作前
  3. DELETEORINSERTORUPDATE--由三种事件触发
  4. ONemp
  5. FOREACHROW--行级触发器
  6. BEGIN
  7. IFINSERTINGTHEN
  8. INSERTINTOlogsVALUES(logs_id_squ.NEXTVAL,'EMP','INSERT',:new.empno,SYSDATE,USER);
  9. ELSIFDELETINGTHEN
  10. INSERTINTOlogsVALUES(logs_id_squ.NEXTVAL,'EMP','DELETE',:old.empno,SYSDATE,USER);
  11. ELSE
  12. INSERTINTOlogsVALUES(logs_id_squ.NEXTVAL,'EMP','UPDATE',:new.empno,SYSDATE,USER);
  13. ENDIF;
  14. END;

执行结果:
触发器已创建
步骤4:在EMP表中插入记录:
Sql代码
  1. INSERTINTOemp(empno,ename,job,sal)VALUES(8001,'MARY','CLERK',1000);
  2. COMMIT;

执行结果:
Sql代码
  1. 已创建1行。
  2. 提交完成。

步骤5:检查LOGS表中记录的信息:
Sql代码
  1. SELECT*FROMLOGS;

执行结果为:
Sql代码
  1. LOG_IDLOG_TABLELOG_DMLLOG_KEY_IDLOG_DATELOG_USER
  2. --------------------------------------------------------------------------------------------------------------
  3. 1EMPINSERT800129-3月-04STUDENT
  4. 已选择1行。

说明:本例中在emp表上创建了一个由INSERT或DELETE或UPDATE事件触发的行级触发器,触发器的名称是LOG_EMP。对于不同的操作,记录的内容不同。本例中只插入了一条记录,如果用一条不带WHERE条件的UPDATE语句来修改所有雇员的工资,则将逐行触发触发器。
INSERT、DELETE和UPDATE都能引发触发器动作,在分支语句中使用INSERTING、DELETING和UPDATING来区别是由哪种操作引发的触发器动作。
在本例的插入动作中,LOG_ID字段由序列LOG_ID_SQU自动填充为1;LOGS表LOG_KEY_ID字段记录的是新插入记录的主键8001;LOD_DML字段记录的是插入动作INSERT;LOG_TABLE字段记录当前表名EMP;LOG_DATE字段记录插入的时间04年3月1日;LOG_USER字段记录插入者STUDENT。
【练习1】修改、删除刚刚插入的雇员记录,提交后检查LOGS表的结果。
【练习2】为DEPT表创建同样的触发器,使用LOGS表进行记录,并检验结果。
【训练2】 创建一个行级触发器LOG_SAL,记录对职务为CLERK的雇员工资的修改,且当修改幅度超过200时才进行记录。用WHEN条件限定触发器。
在创建触发器之前,需要先创建事件记录表LOGERR,该表用来对操作进行记录。该表的字段含义解释如下:
NUM:数值型,用于记录序号。
MESSAGE:字符型,用于记录错误信息。
步骤1:在SQL*Plus中登录STUDENT账户,创建如下的记录表LOGERR:
Sql代码
  1. CREATETABLElogerr(
  2. NUMNUMBER(10)NOTNULL,
  3. MESSAGEVARCHAR2(50)NOTNULL
  4. );

执行结果:
Sql代码
  1. 表已创建。

步骤2:创建和编译以下触发器:
Sql代码
  1. CREATEORREPLACETRIGGERlog_sal
  2. BEFORE
  3. UPDATEOFsal
  4. ONemp
  5. FOREACHROW
  6. WHEN(new.job='CLERK'AND(ABS(new.sal-old.sal)>200))
  7. DECLARE
  8. v_noNUMBER;
  9. BEGIN
  10. SELECTCOUNT(*)INTOv_noFROMlogerr;
  11. INSERTINTOlogerrVALUES(v_no+1,'雇员'||:new.ename||'的原工资:'||:old.sal||'新工资:'||:new.sal);
  12. END;

执行结果:
Sql代码
  1. 触发器已创建。

步骤3:在EMP表中更新记录:
Sql代码
  1. UPDATEempSETsal=sal+550WHEREempno=7788;
  2. UPDATEempSETsal=sal+500WHEREempno=7369;
  3. UPDATEempSETsal=sal+50WHEREempno=7876;
  4. COMMIT;

执行结果:
Sql代码
  1. 已更新1行。
  2. 已更新1行。
  3. 已更新1行。
  4. 提交完成。

步骤4:检查LOGSAL表中记录的信息:
Sql代码
  1. SELECT*FROMlogerr;

执行结果为:
Sql代码
  1. NUMMESSAGE
  2. --------------------------------------------------------------------------
  3. 1雇员SMITH的原工资:800新工资:1300
  4. 已选择1行。

说明:本例中,在emp表的sal列上创建了一个由UPDATE事件触发的行级触发器,触发器的名称是LOG_SAL。该触发器由WHEN语句限定,只有当被修改工资的雇员职务为CLERK,且修改的工资超过200时才进行触发,否则不进行触发。
所以在验证过程中,虽然修改了3条记录,但通过查询语句发现:第一条修改语句修改编号为7788的SCOTT记录,因为SCOTT的职务是ANALYST,不符合WHEN条件,没有引起触发器动作;第二条修改语句修改编号为7369的SMITH的记录,职务为CLERK,因为增加的工资(500)超过了200,所以引起触发器动作,并在LOGERR表中进行了记录;第三条修改语句修改编号为7876的雇员ADAMS的记录,虽然ADAMS的职务为CLERK,但修改的工资(50)没有超过200,所以没有引起触发器动作。
注意:在WHEN条件中引用new和old不需要在前面加“: ”。
在以上实例中,记录了对工资的修改超出范围的信息,但没有限制对工资的修改。那么当对雇员工资的修改幅度不满足条件时,能否直接限制对工资的修改呢?答案是肯定的。
【训练3】 创建触发器CHECK_SAL,当对职务为CLERK的雇员的工资修改超出500至2000的范围时,进行限制。
步骤1:创建和编译以下触发器:
Sql代码
  1. CREATEORREPLACETRIGGERCHECK_SAL
  2. BEFORE
  3. UPDATE
  4. ONemp
  5. FOREACHROW
  6. BEGIN
  7. IF:new.job='CLERK'AND(:new.sal<500OR:new.sal>2000)THEN
  8. RAISE_APPLICATION_ERROR(-20001,'工资修改超出范围,操作取消!');
  9. ENDIF;
  10. END;

执行结果:
Sql代码
  1. 触发器已创建。

步骤2:在EMP表中插入记录:
Sql代码
  1. UPDATEempSETsal=800WHEREempno=7876;
  2. UPDATEempSETsal=450WHEREempno=7876;
  3. COMMIT;

执行结果:
Sql代码
  1. UPDATEempSETsal=450WHEREempno=7876
  2. *
  3. ERROR位于第1行:
  4. ORA-20001:工资修改超出范围,操作取消!
  5. ORA-06512:在"STUDENT.CHECK_SAL",line3
  6. ORA-04088:触发器'STUDENT.CHECK_SAL'执行过程中出错提交完成。

步骤3:检查工资的修改结果:
Sql代码
  1. SELECTempno,ename,job,salFROMempkeywo
分享到:
评论

你可能感兴趣的:(设计模式,oracle,sql,sql,应用服务器,server)