ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 触发器学习

触发器学习

原创 Linux操作系统 作者:rabbity 时间:2010-11-18 15:11:10 0 删除 编辑

触发器

是特定事件出现的时候,自动执行的代码块。类似于存储过程,但是用户不能直接调用他们。

功能:
1、 允许/限制对表的修改
2、 自动生成派生列,比如自增字段
3、 强制数据一致性
4、 提供审计和日志记录
5、 防止无效的事务处理
6、 启用复杂的业务逻辑

创建触发器的一般语法是:

CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF}
{INSERT | DELETE | UPDATE [OF column [, column …]]}
ON {[schema.] table_name | [schema.] view_name}
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
trigger_body;


其中:
    BEFORE 和AFTER指出触发器的触发时序分别为前触发和后触发方式,前触发是在执行触发事件之前触发当前所创建的触发器,后触发是在执行触发事件之后触发当前所创建的 触发器。
    INSTEAD OF 选项使ORACLE激活触发器,而不执行触发事件。只能对视图和对象视图建立INSTEAD OF触发器,而不能对表、模式和数据库建立INSTEAD OF 触发器。
    FOR EACH ROW选项说明触发器为行触发器。行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操走影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则为行触发器。
    REFERENCING 子句说明相关名称,在行触发器的PL/SQL块和WHEN 子句中可以使用相关名称参照当前的新、旧列值,默认的相关名称分别为OLD和NEW。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在WHEN子句中则不能加冒号。
    WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。WHEN 子句指定的触发约束条件只能用在BEFORE 和AFTER 行触发器中,不能用在INSTEAD OF 行触发器和其它类型的触发器中。
    当一个基表被修改( INSERT, UPDATE, DELETE)时要执行的存储过程,执行时根据其所依附的基表改动而自动触发,因此与应用程序无关,用数据库触发器可以保证数据的一致性和完整性。

 触发器的限制:
    CREATE TRIGGER语句文本的字符长度不能超过32KB;
    触发器体内的SELECT 语句只能为SELECT … INTO …结构,或者为定义游标所使用的SELECT 语句。
    触发器中不能使用数据库事务控制语句 COMMIT; ROLLBACK, SVAEPOINT 语句;
    由触发器所调用的过程或函数也不能使用数据库事务控制语句;
    触发器中不能使用LONG, LONG RAW 类型;
    触发器内可以参照LOB 类型列的列值,但不能通过 :NEW 修改LOB列中的数据;
    触发器所访问的表受到表的约束限制,即后面的“变化表”

(Instead_of)触发器:
    INSTEAD_OF 用于对视图的DML触发,由于视图有可能是由多个表进行联结(join)而成,因而并非是所有的联结都是可更新的。但可以按照所需的方式执行更新,例如下面情况:

CREATE OR REPLACE VIEW emp_view AS
SELECT deptno, count(*) total_employeer, sum(sal) total_salary
FROM emp GROUP BY deptno;

在此视图中直接删除是非法:
SQL>DELETE FROM emp_view WHERE deptno=10;
DELETE FROM emp_view WHERE deptno=10
            *
ERROR 位于第 1 行:
ORA-01732: 此视图的数据操纵操作非法

但是我们可以创建INSTEAD_OF触发器来为 DELETE 操作执行所需的处理,即删除EMP表中所有基准行:

CREATE OR REPLACE TRIGGER emp_view_delete
   INSTEAD OF DELETE ON emp_view FOR EACH ROW
BEGIN
   DELETE FROM emp WHERE deptno= :old.deptno;
END emp_view_delete;

DELETE FROM emp_view WHERE deptno=10;

DROP TRIGGER emp_view_delete;
DROP VIEW emp_view;

创建系统事件触发器:

ORACLE8i提供的系统事件触发器可以在DDL或数据库系统上被触发。DDL指的是数据定义语言,如CREATE 、ALTER及DROP 等。而数据库系统事件包括数据库服务器的启动或关闭,用户的登录与退出、数据库服务错误等。创建系统触发器的语法如下:

CREATE OR REPLACE TRIGGER [sachema.] trigger_name
   {
BEFORE|AFTER}  {ddl_event_list|database_event_list}
  
ON { DATABASE | [schema.] SCHEMA }
   [ WHEN_clause]
   trigger_body;
其中:
ddl_event_list:一个或多个DDL 事件,事件间用 OR 分开;
    
database_event_list:一个或多个数据库事件,事件间用 OR 分开;
    系统事件触发器既可以建立在一个模式上,又可以建立在整个数据库上。当建立在模式之上时,只有模式所指定用户的DDL操作和它们所导致的错误才激活触发器;当建立在数据库之上时,该数据库所有用户的DDL操作和他们所导致的错误,以及数据库的启动和关闭均可激活触发器。要在数据库之上建立触发器时,要求用户具有ADMINISTER DATABASE TRIGGER权限。

下面给出系统触发器的种类和事件出现的时机(前或后):
事件    允许的时机    说明
启动STARTUP    之后    实例启动时激活
关闭SHUTDOWN    之前    实例正常关闭时激活
服务器错误SERVERERROR    之后    只要有错误就激活
登录LOGON    之后    成功登录后激活
注销LOGOFF    之前    开始注销时激活
创建CREATE     之前,之后    在创建之前或之后激活
撤消DROP    之前,之后    在撤消之前或之后激活
变更ALTER    之前,之后    在变更之前或之后激活

    系统触发器可以在数据库级(database)或模式(
schema)级进行定义。数据库级触发器在任何事件都激活触发器,即触发对象为整个数据库中所有用户产生的每个指定事件;而模式触发器只有在指定的模式所产生的的触发事件发生时才触发,默认时为当前用户模式。

    系统级触发器事件:

 Ora_client_ip_address 返回客户端的ip地址
      Ora_database_name 返回当前数据库名
      Ora_des_encrypted_password 返回des加密后的用户口令
      Ora_dict_obj_name 返回ddl操作所对应的数据库对象名
      Ora_dict_obj_name_list(name_list out ora_name_list_t) 返回在事件中被修改的对象名列表
      Ora_dict_obj_owner 返回ddl操作所对应的对象的所有者名
      Ora_dict_obj_owner_list(owner_list out ora_name_list_t) 返回在事件中被修改的对象的所有者列表
      Ora_dict_obj_type 返回ddl操作所对应的数据库对象的类型
      Ora_grantee(user_list out ora_name_list_t) 返回授权事件的授权者
      Ora_instance_num 返回例程号
      Ora_is_alter_column(column_name in varchar2) 检测特定列是否被修改
      Ora_is_creating_nested_table 检测是否正在建立嵌套表
      Ora_is_drop_column(column_name in varchar2) 检测特定列是否被删除
      Ora_is_servererror(error_number) 检测是否返回了特定oracle错误
      Ora_login_user 返回登录用户名
      Ora_sysevent 返回触发器的系统事件名。

 8i开始提供了一个新的函数“SYS_CONTEXT”。通过使用SYS_CONTEXT函数可以获得一些和用户相关的信息,比如:

SELECT sys_context('USERENV','TERMINAL') FROM DUAL;

用户环境的取值包括:

TERMINAL:客户端操作系统终端的名称   
LANGUAGE:NLS_LANG的值
LANG  :ISO字符集的名称.
SESSIONID:SESSION的ID
INSTANCE:实例的ID
ISDBA:是否具有DBA权限
CLIENT_INFO:64字节的用户信息,可以用DBMS_APPLICATION_INFO设置的值:
NLS_TERRITORY :当前SESSION的 territory
NLS_CURRENCY:当前SESSION的货币符
NLS_CALENDAR:当前SESSION的历法
NLS_DATE_FORMAT:当前SESSION的日期格式
NLS_DATE_LANGUAGE :显示日期的语言
NLS_SORT:排序方式(BINARY 或者linguistic)
CURRENT_USER:当前SESSION拥有权限的用户的名称(比如说当前SESSION是SYS,但是正在执行system.myproc,那么current_user就是system)
CURRENT_USERID :当前SESSION拥有的权限的用户的ID
SESSION_USER:session所属的用户名
SESSION_USERID:当前SESSION所属的用户id
CURRENT_SCHEMA:当前SESSION缺省的SCHEMA名称,可以用SESSION SET CURRENT_SCHEMA 语句修改.
CURRENT_SCHEMAID :当前SESSION缺省的SCHEMA的ID
PROXY_USER:打开当前SESSION的用户的名称
PROXY_USERID:打开当前SESSION的用户的ID
DB_DOMAIN:当前数据库的DOMAIN
DB_NAME:当前数据库的名称
HOST:客户端的主机名称
OS_USER:客户端的操作系统用户名
EXTERNAL_NAME:用户的外部名称。对于SSL用户,使用v.503协议,返回的值是证书中的DN
IP_ADDRESS:客户端的IP地址
NETWORK_PROTOCOL:连接串中的PROTOCOL=protocol指明的网络协议
BG_JOB_ID :如果当前的SESSION是由ORACLE后台进程启动的,那么返回JOB_ID,否则返回空值
FG_JOB_ID:如果当前SESSION是由ORACLE客户端进程启动的一个JOB,那么返回JOB_ID,否则返回空值
AUTHENTICATION_TYPE:返回数据库鉴权的方法,返回值包括:
DATABASE: 使用数据库的用户名口令
OS:使用操作系统外部用户鉴权
NETWORK:网络鉴权
PROXY:OCI的代理连接鉴权
AUTHENTICATION_DATA:使用X.503证书鉴权的时候,返回HEX2的证书

   


 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/77950/viewspace-678432/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2010-11-18

  • 博文量
    4
  • 访问量
    6053