ORACLE 12C存儲過程ALTER Trigger出現ORA-01031錯誤

1.問題處理

1.1 錯誤背景

數據庫版本: ORACLE 12.2.0.1 CDB模式
涉及對象:

  • 數據庫用戶:USER1(創建用戶)、USER2(調用用戶)
  • 觸發器:USER1.TriggerTst(on database)
  • 存儲過程:USER1.P_callTrigger(使用execute immediate方式alter trigger)

錯誤場景:
用戶USER1和用戶USER2調用存儲過程USER1.P_callTrigger進行alter trigger操作出現“ORA-01031”錯誤,錯誤信息如下:

ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "*****",line ****

1.2 錯誤分析

分別檢查對象屬主USER1和調用用戶USER2的角色權限和對象權限,均擁有dba權限,均擁有ALTER ANY TRIGGER權限

--通過如下語句檢查角色權限
select * from dba_sys_privs where grantee='USER1' and privilelge like '%TRIGGER';
--輸出包含ALTER ANY TRIGGER/CREATE ANY TRIGGER

select * from dba_role_privs where grantee='USER1' 
--輸出包含DBA角色

若無對應權限,可以手動單獨顯式授權

sqlplus / as sysdba
alter session set container=XXX; 
grant create any trigger to USER1;
grant alter any trigger to USER1;
grant dba to USER1;

1.3 解決方法

檢查PLSQL中“系統權限”部分與觸發器相關權限,併爲用戶USER1增加administer database trigger權限,問題解決。

2.權限說明

關於administer database trigger權限,官方文檔《SQL Language Reference》“ALTER TRIGGER”章節中有如下說明:

Prerequisites
The trigger must be in your own schema or you must have ALTER ANY TRIGGER system privilege.
In addition, to alter a trigger on DATABASE, you must have the ADMINISTER DATABASE TRIGGER privilege.

3.測試案例

3.1 環境準備

數據庫版本:12.2.0.1:

--01.創建用戶及授權
create user test identified by  "23456";
grant connect,resource to test;
grant alter  any trigger to test;
grant execute on test2.p_ddltrg to test;
--grant dba to test;
create user test2 identified by  "23456";
grant connect,resource to test2;
grant create any trigger to test2;
grant create any table to test2;
grant create any procedure to test2;
grant alter  any trigger to test2;
--grant dba to test2;

--02.創建測試表
create table test2.t_test(ttime date);

--03.創建觸發器
create or replace trigger test2.TrgBfTst
  before ddl on database
begin
  insert into test2.t_test(ttime) values(sysdate);
  --commit;
end;
/

--04.創建存儲過程
create or replace procedure test2.p_ddltrg(pi_flag varchar2)
is
  v_i number;
begin
  select max(1) into v_i
    from user_triggers t where t.trigger_name='TRGBFTST';

  if v_i is not null then
    if pi_flag = 'D' then
       execute immediate 'alter trigger TrgBfTst disable';
    elsif pi_flag ='E' then
       execute immediate 'alter trigger TrgBfTst enable';
    end if;

  end if;
end;
/

3.2 測試方法

方式1:直接進行alter trigger

alter trigger test2.TrgBfTst disable;alter trigger test2.TrgBfTst enable;

方式2:調用存儲過程進行alter trigger

call test2.p_ddltrg('E');call test2.p_ddltrg('D');

3.3 測試情況

總結:

  • CDB模式下:數據庫無DBA權限時無法創建觸發器TrgBfTst(授予DBA權限後可以創建成功)
  • 非CDB模式下:數據庫無DBA權限時可以創建觸發器TrgBfTst
--授予此權限後可以在存儲過程中執行alter trigger
grant administer database trigger to test2;
--revoke administer database trigger from test2;

備註:以下表格中/兩邊分別爲無administer database trigger和有administer database trigger權限時對應的操作是否可以執行

CDB 創建者(DBA權限) 非創建者(DBA權限) 非創建者(無DBA權限)
alter trigger yes/yes no/yes no/no
call p_ddltrg no/yes no/yes no/yes
非CDB 創建者(無DBA權限) 非創建者(DBA權限) 非創建者(無DBA權限)
alter trigger yes/yes no/yes no/no
call p_ddltrg no/yes no/yes no/yes
非CDB 創建者(DBA權限) 非創建者(DBA權限) 非創建者(無DBA權限)
alter trigger yes/yes no/yes no/no
call p_ddltrg no/yes no/yes no/yes
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章