Oracle觸發器3-DDL觸發器

來源:互聯網
上載者:User

DDL觸發器,當執行DDL語句時會被觸發。按照作用範圍,分為schema triggers,database triggers。schema triggers作用在一個使用者上,database triggers作用在整個資料庫所有使用者上。

建立DDL觸發器

要建立一個DDL觸發器,文法如下:

1 CREATE [OR REPLACE] TRIGGER trigger name                         --建立一個觸發器並制定名稱,or replace是可選項
2 {BEFORE | AFTER } { DDL event} ON {DATABASE | SCHEMA}     --指定觸發器是在DDL事件之前、之後觸發。範圍是on database、on schema
3 [WHEN (...)]                                                                               --可選的WHEN子句,使用邏輯判斷來避免觸發器無意義的執行
4 DECLARE                                                                                  --觸發器具體內容4-7

5 Variable declarations
6 BEGIN
7 ...some code...
8 END;

Examples:

SQL> CREATE OR REPLACE TRIGGER hr.testtrigger
2 AFTER CREATE ON SCHEMA  -- on schema 作用範圍只是在hr使用者下create table等觸發,其他使用者則不會。若是on database則其他使用者create table時會觸發該觸發器
3 BEGIN
4   -- 以下使用的是事件屬性
5 DBMS_OUTPUT.PUT_LINE('I believe you have created a ' ||
6 ORA_DICT_OBJ_TYPE || ' called ' ||
7 ORA_DICT_OBJ_NAME);
8 END;
9 /
Trigger created.

可用事件

                                            可用的DDL事件

DDL事件 觸發時機
ALTER 對資料庫中的任何一個對象使用SQL的ALTER命令時觸發
ANALYZE 對資料庫中的任何一個對象使用SQL的ANALYZE命令時觸發
ASSOCIATE STATISTICS 統計資料關聯到資料庫物件時觸發
AUDIT 通過SQL的AUDIT命令開啟審計時觸發
COMMENT 對資料庫物件做注釋時觸發
CREATE 通過SQL的CREATE命令建立資料庫物件時觸發
DDL 列表中所用的事件都會觸發
DISASSOCIATE STATISTICS 去掉統計資料和資料庫物件的關聯時觸發
DROP 通過SQL的DROP命令刪除資料庫物件時觸發
GRANT 通過SQL的GRANT命令賦權時觸發
NOAUDIT 通過SQL的NOAUDIT關閉審計時觸發
RENAME 通過SQL的RENAME命令對對象重新命名時觸發
REVOKE 通過SQL的REVOKE語句撤銷授權時觸發
TRUNCATE 通過SQL的TRUNCATE語句截斷表時觸發
可用屬性

Oracle 提供了一系列的函數用來提供關於什麼觸發了DDL觸發器以及觸發器的狀態燈資訊。上面那個觸發器的例子就使用了屬性。

                                                       DDL觸發事件以及屬性函數

函數名 傳回值
ORA_CLIENT_IP_ADDRESS 用戶端IP地址
ORA_DATABASE_NAME 資料庫名稱
ORA_DES_ENCRYPTED_PASSWORD 目前使用者的DES演算法加密後的密碼
ORA_DICT_OBJ_NAME 觸發DDL的資料庫物件名稱
ORA_DICT_OBJ_NAME_LIST 受影響的對象數量和名稱列表
ORA_DICT_OBJ_OWNER 觸發DDL的資料庫物件屬主
ORA_DICT_OBJ_OWNER_LIST 受影響的對象數量和名稱列表
ORA_DICT_OBJ_TYPE 觸發DDL的資料庫物件類型
ORA_GRANTEE 被授權人數量
ORA_INSTANCE_NUM 資料庫執行個體數量
ORA_IS_ALTER_COLUMN 如果操作的參數column_name指定的列,返回true,否則false
ORA_IS_CREATING_NESTED_TABLE 如果正在建立一個巢狀表格則返回true,否則false
ORA_IS_DROP_COLUMN 如果刪除的參數column_name指定的列,返回true,否則false
ORA_LOGIN_USER 觸發器所在的使用者名稱
ORA_PARTITION_POS SQL命令中可以正確添加分區子句位置
ORA_PRIVILEGE_LIST 授予或者回收的許可權的數量。
ORA_REVOKEE 被回收者的數量
ORA_SQL_TXT 觸發了觸發器的SQL語句的行數。
ORA_SYSEVENT 導致DDL觸發器被觸發的時間
ORA_WITH_GRANT_OPTION 如果授權帶有grant選項,返回true。否則false

更多屬性函數請參考官方文檔PL/SQL Language Reference -> Triggers and Oracle Database Data Transfer Utilities

使用事件和屬性

Examples:

--建立資料庫物件時發出警告,刪除資料庫物件時阻止

CREATE OR REPLACE TRIGGER HR.no_drop
BEFORE DDL ON DATABASE
BEGIN
IF ORA_SYSEVENT = 'CREATE'
THEN
DBMS_OUTPUT.PUT_LINE('Warning !!! You have created a '||
                        ORA_DICT_OBJ_TYPE ||' called '||
                        ORA_DICT_OBJ_NAME|| '; UserName(creater):'||
                        ORA_DICT_OBJ_OWNER||'; IP:'||
                        ORA_CLIENT_IP_ADDRESS||'; event:'||
                        ORA_SYSEVENT);                       
ELSIF ORA_SYSEVENT = 'DROP'
THEN
RAISE_APPLICATION_ERROR (-20000,
'Cannot create the ' || ORA_DICT_OBJ_TYPE ||
' named ' || ORA_DICT_OBJ_NAME ||
' as requested by ' || ORA_DICT_OBJ_OWNER);
END IF;
END;

--操作了資料庫表的哪一列

CREATE OR REPLACE TRIGGER preserve_app_cols
   AFTER ALTER ON SCHEMA
DECLARE
   -- cursor to get columns in a table
   CURSOR curs_get_columns (cp_owner VARCHAR2, cp_table VARCHAR2)
   IS
      SELECT column_name
        FROM all_tab_columns
       WHERE owner = cp_owner AND table_name = cp_table;
BEGIN
   -- if it was a table that was altered...
   IF ora_dict_obj_type = 'TABLE'
   THEN
      -- for every column in the table...
      FOR v_column_rec IN curs_get_columns (
                             ora_dict_obj_owner,
                             ora_dict_obj_name
                          )
      LOOP
         -- if the current column was the one that was altered then say so
         IF ora_is_alter_column (v_column_rec.column_name)
         THEN
            -- if the table/column is core?
            IF is_application_column (
                  ora_dict_obj_owner,
                  ora_dict_obj_name,
                  v_column_rec.column_name
               )
            THEN
               RAISE_APPLICATION_ERROR (
                  -20001,
                  'Cannot alter core application attributes'
               );
            END IF; -- table/column is core
         END IF; -- current column was altered
      END LOOP; -- every column in the table
   END IF; -- table was altered
END;
--屬性函數傳回值列表

CREATE OR REPLACE TRIGGER hr.what_privs
   AFTER GRANT ON SCHEMA
DECLARE
   v_grant_type     VARCHAR2 (30);
   v_num_grantees   BINARY_INTEGER;
   v_grantee_list   ora_name_list_t;
   v_num_privs      BINARY_INTEGER;
   v_priv_list      ora_name_list_t;
BEGIN
   v_grant_type := ora_dict_obj_type;
   v_num_grantees := ora_grantee (v_grantee_list);
   v_num_privs := ora_privilege_list (v_priv_list);

   IF v_grant_type = 'ROLE PRIVILEGE'
   THEN
      DBMS_OUTPUT.put_line (
         CHR (9) || 'The following roles/privileges were granted'
      );

      FOR counter IN 1 .. v_num_privs
      LOOP
         DBMS_OUTPUT.put_line (
            CHR (9) || CHR (9) || 'Privilege ' || v_priv_list (counter)
         );
      END LOOP;
   ELSIF v_grant_type = 'OBJECT PRIVILEGE'
   THEN
      DBMS_OUTPUT.put_line (
         CHR (9) || 'The following object privileges were granted'
      );

      FOR counter IN 1 .. v_num_privs
      LOOP
         DBMS_OUTPUT.put_line (
            CHR (9) || CHR (9) || 'Privilege ' || v_priv_list (counter)
         );
      END LOOP;

      DBMS_OUTPUT.put (CHR (9) || 'On ' || ora_dict_obj_name);

      IF ora_with_grant_option
      THEN
         DBMS_OUTPUT.put_line (' with grant option');
      ELSE
         DBMS_OUTPUT.put_line ('');
      END IF;
   ELSIF v_grant_type = 'SYSTEM PRIVILEGE'
   THEN
      DBMS_OUTPUT.put_line (
         CHR (9) || 'The following system privileges were granted'
      );

      FOR counter IN 1 .. v_num_privs
      LOOP
         DBMS_OUTPUT.put_line (
            CHR (9) || CHR (9) || 'Privilege ' || v_priv_list (counter)
         );
      END LOOP;
   ELSE
      DBMS_OUTPUT.put_line ('I have no idea what was granted');
   END IF;

   FOR counter IN 1 .. v_num_grantees
   LOOP
      DBMS_OUTPUT.put_line (
         CHR (9) || 'Grant Recipient ' || v_grantee_list (counter)
      );
   END LOOP;
END;
/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.