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 |