Oracle-Trigger-DDL-1

DDL触发器

当创建、修改或者删除数据库对象时,也会引起相应的触发器操作事件,而此时就可以利用触发器来对这些数据库对象的 DDL 操作进行监控,DDL 触发器的创建语法如下所示。

CREATE [ OR REPLACE ] TRIGGER 触发器名称
[BEFORE | AFTER | INSTEAD  OF] [DDL 事件] ON [DATABASE | SCHEMA]
[WHEN 触发条件]
[DECLARE]
[程序声明部分;]
BEGIN
    程序代码部分;
END [触发器名称];
/

DDL触发器支持事件

DDL事件 触发时机 描述
ALTER BEFORE/AFTER 修改对象的结构时触发
ANALYZE BEFORE/AFTER 分析数据库对象时触发
ASSOCIATE STATISTICS BEFORE/AFTER 启动统计数据库对象时触发
AUDIT BEFORE/AFTER 开启审核数据库对象时触发
COMMENT BEFORE/AFTER 为数据库对象设置注释信息时触发
CREATE BEFORE/AFTER 创建数据库对象时触发
DDL BEFORE/AFTER 针对于出现的所有DDL事件触发
DISASSOCIATE STATISTICS BEFORE/AFTER 关闭统计数据库对象时触发
DROP BEFORE/AFTER 删除数据库对象时触发
GRANT BEFORE/AFTER 用户授权时触发
NOAUDIT BEFORE/AFTER 禁用审核数据库对象时触发
RENAME BEFORE/AFTER 为数据库对象重命名时触发
REVOKE BEFORE/AFTER 用户撤销权限时触发
TRUNCATE BEFORE/AFTER 截断数据表时触发

常用的事件属性函数

事件属性函数 描述
ORA_CLIENT_IP_ADDRESS 取得客户端IP地址,如果是本地连接则返回NULL,返回数据类型为VARCHAR2
ORA_DATABASE_NAME 取得数据库名称,返回的数据类型为VARCHAR2
ORA_DES_ENCRYPTED_PASSWORD 取得加密后的口令内容,返回数据类型为VARCHAR2
ORA_DICT_OBJ_NAME 取得对象名称,返回数据类型为VARCHAR2
ORA_DICT_OBJ_NAME_LIST(nameList OUT ORA_NAME_LIST_T) 返回被修改的对象名称列表
ORA_DICT_OBJ_OWNER 取得对象的拥有者,返回数据类型为VARCHAR2
ORA_DICT_OBJ_OWNER_LIST(objList OUT ORA_NAME_LIST_T) 返回被修改对象的所有列表
ORA_DICT_OBJ_TYPE 返回对象类型
ORA_GRANTEE(nameList OUT ORA_NAME_LIST_T) 返回授予的权限或角色列表
ORA_INSTANCE_NUM 取得当前数据库之中的实例编号
ORA_IS_ALTER_COLUMN(column Name VARCHAR2) 判断列名称是否被修改,返回数据类型为BOOLEAN
ORA_IS_CREATING_NESTED_TABLE 如果创建一个嵌套表,返回数据类型为BOOLEAN
ORA_IS_DROP_COLUMN(columnName VARCHAR2) 判断一个列是否被删除,返回数据类型为BOOLEAN
ORA_IS_SERVERERROR(errorCode Number) 判断是否出现了指定的错误编号,返回数据类型为BOOLEAN
ORA_LOGIN_USER 取得当前模式名称,返回的数据类型为VARCHAR2
ORA_REVOKEE(nameList OUT ORA_NAME_LIST_T) 返回撤销的权限或角色列表
ORA_SERVER_ERROR(point NUMBER) 返回错误堆栈信息中的错误号,其中1为错误堆栈顶端,返回的数据类型为NUMBER
ORA_SERVER_ERROR_MSG 返回错误堆栈信息中的错误信息,其中1为错误堆栈顶端,返回数据类型为VARCHAR2
ORA_SYSEVENT 返回触发器的操作事件,返回的数据类型为VARCHAR2

范例

范例 1 :使用 scott 用户创建 禁止 scott 用户的所有 DDL 操作

create or replace trigger scott_forbid_trigger
before DDL
ON SCHEMA
BEGIN
   RAISE_APPLICATION_ERROR(-20007,'Scott is forbid any DDL');
END;
/

范例 2:创建一个记录对象日志信息表,并记录用户操作对象的日志

创建各个数据库对象的日志信息表

DROP TABLE object_log PURGE;
DROP SEQUENCE object_log_seq;
CREATE SEQUENCE object_log_seq;
CREATE TABLE object_log(
 oid            NUMBER,
 username       VARCHAR2(50) NOT NULL ,
 operatedate    DATE NOT NULL,
 objecttype     VARCHAR2(50) NOT NULL,
 objectowner    VARCHAR2(50) NOT NULL,
 CONSTRAINT pk_oid PRIMARY KEY (oid)
);

触发器

create or replace trigger object_trigger
before CREATE OR DROP OR ALTER
ON DATABASE
BEGIN
   INSERT INTO
   object_log(oid,username,operatedate,objecttype,objectowner)
   VALUES(object_log_seq.nextval,ora_login_user,SYSDATE,ora_dict_obj_type,ora_dict_obj_owner);
END;
/

范例 3:禁止修改 emp 数据表的 empno(主键) 列和 deptno(外键)列的定义结构

需要知道列的信息,可以使用 all_tab_columns 数据字典

CREATE OR REPLACE TRIGGER emp_alter_triger
BEFORE ALTER 
ON SCHEMA
DECLARE
   CURSOR emp_column_cur(p_tableOwner all_tab_columns.owner%TYPE,
   p_tableName all_tab_columns.table_name%TYPE) IS
   SELECT column_name from all_tab_columns
   where owner=p_tableOwner AND table_name=p_tableName;
BEGIN
   IF ora_dict_obj_type = 'TABLE' THEN
     FOR empColumnRow IN emp_column_cur(ora_dict_obj_owner,
       ora_dict_obj_name) LOOP
       IF ora_is_alter_column(empColumnRow.column_name) THEN
         IF empColumnRow.column_name = 'EMPNO' THEN
           RAISE_APPLICATION_ERROR(-20007,'empno is can not update');
         END IF;
         IF empColumnRow.column_name = 'DEPTNO' THEN
           RAISE_APPLICATION_ERROR(-20008,'deptno is can not update');
         END IF;
        END IF;
        IF ora_is_drop_column(empColumnRow.column_name) THEN
         IF empColumnRow.column_name = 'EMPNO' THEN
           RAISE_APPLICATION_ERROR(-20009,'empno is can not delete');
         END IF;
         IF empColumnRow.column_name = 'DEPTNO' THEN
           RAISE_APPLICATION_ERROR(-20010,'deptno is can not delete');
         END IF;
        END IF;
      END LOOP;
    END IF;
END;
/
Contents
  1. 1. DDL触发器
    1. 1.1. DDL触发器支持事件
    2. 1.2. 常用的事件属性函数
    3. 1.3. 范例
      1. 1.3.1. 范例 1 :使用 scott 用户创建 禁止 scott 用户的所有 DDL 操作
      2. 1.3.2. 范例 2:创建一个记录对象日志信息表,并记录用户操作对象的日志
      3. 1.3.3. 范例 3:禁止修改 emp 数据表的 empno(主键) 列和 deptno(外键)列的定义结构
|