存儲過程權限及存儲過程中的ddl語句

1 定義者存儲過程role無效,必須要顯式授權

-- 創建用戶 abc ,並授予dba權限

create user abc identified by oracle;
grant dba to abc;
SYS@test>create user abc identified by oracle;

User created.

SYS@test>grant dba to abc;

Grant succeeded.

SYS@test>

-- 使用abc用戶登錄,創建表t1 ;

conn abc/oracle 
create table t1 as select * from dba_objects;

SYS@test>conn abc/oracle
Connected.
ABC@test>create table t1 as select * from dba_objects;

Table created.

ABC@test>

-- 使用bb用戶,bb用戶擁有dba權限,在sqlplus上可以刪除表t1,

conn bb/oracle 
delete from t1;
rollback;

BB@test>delete from abc.t1 ;

72975 rows deleted.

BB@test>rollback;

Rollback complete.

BB@test>

-- 在bb下創建存儲過程,存儲過程刪除abc.t1表,發現建立的存儲過程有warning ,提示表或者視圖不存在

create or replace procedure p_bb_t1 as 
begin 
delete from abc.t1;
commit;
end;
/

BB@test>create or replace procedure p_bb_t1 as
begin
delete from abc.t1;
commit;
end;
/  2    3    4    5    6

Warning: Procedure created with compilation errors.



BB@test>show error
Errors for PROCEDURE P_BB_T1:

LINE/COL ERROR
-------- -----------------------------------------------------------------
3/1      PL/SQL: SQL Statement ignored
3/17     PL/SQL: ORA-00942: table or view does not exist
BB@test>

-- 授權abc.t1表的所有權限給bb

grant all on abc.t1 to bb;

SYS@test>grant all on abc.t1 to bb;

Grant succeeded.

-- 重新創建存儲過程,可以了。

conn bb/oracle 
create or replace procedure p_bb_t1 as 
begin 
delete from abc.t1;
commit;
end;
/

SYS@test>conn bb/oracle
Connected.
BB@test>create or replace procedure p_bb_t1 as
begin
delete from abc.t1;
commit;
end;
/  2    3    4    5    6

Procedure created.

BB@test>

2 調用者權限存儲過程role編譯不可見,運行可見

ABC@test>conn bb/oracle
Connected.
BB@test>create or replace procedure p_bb_t1 as
begin
delete from abc.t1;
commit;
end;
/  2    3    4    5    6

Warning: Procedure created with compilation errors.

BB@test>

 
create or replace procedure p_bb_t1 authid current_user as
begin
delete from abc.t1;
commit;
end;
/  

-- 加上 authid current_user(決定role能否在存儲過程中生效)還是出錯  
-- 因爲,存儲過程有編譯和執行兩個階段,編譯階段,調用者權限存儲過程與定義者權限存儲過程是一樣的,角色都是無效的,都必須顯式授權。但是到了執行階段,兩者就有差別了,調用者權限的存儲過程在運行階段時候,role是生效可見的。
-- 下面的例子,添加了authid current_user,在編譯的時候仍然失敗,提示表或者視圖不存在,證實了編譯階段調用者權限和定義者權限是一樣的,角色都是無效的。

BB@test>create or replace procedure p_bb_t1 authid current_user as
begin
delete from abc.t1;
commit;
end;
/    2    3    4    5    6

Warning: Procedure created with compilation errors.

BB@test>

-- 除了加上authid current_user後,在plsql語句中增加execute immediate ,就可以了。使用動態SQL來避免直接授權,而將權限的檢查延後至運行時。

create or replace procedure p_bb_t1 authid current_user as
begin
execute immediate 'delete from abc.t1';
commit;
end;
/ 


BB@test>create or replace procedure p_bb_t1 authid current_user as
begin
execute immediate 'delete from abc.t1';
commit;
end;
/   2    3    4    5    6

Procedure created.

BB@test>

3 存儲過程中的DDL事務提交
DDL語句,在操作的同時,會在當前session完成commit動作,即使ddl操作失敗,也會有commit動作。

-- 在會話1中,插入數據,沒有提交

BB@test>select * from test;

NAME
----
aaaa

bbbb

cccc

BB@test>insert into test values('dddd');

1 row created.

BB@test>

-- 在會話2中,查詢表的數據,看不到會話1中未提交的數據

SYS@test>select * from bb.test;

NAME
----
aaaa

bbbb

cccc

SYS@test>

-- 在會話1中,繼續創建索引,

BB@test>create index idx_test_name on test(name);

Index created.

BB@test>

-- 繼續在會話2中查看錶的數據,發現會話1中未提交的數據,可以看到了。說明DDL語句會進行提交

SYS@test>select * from bb.test;

NAME
----
aaaa

bbbb

cccc
dddd

6 rows selected.

SYS@test>

-- 繼續測試,如果ddl失敗了,會不會提交
-- 在會話1中,刪除1條記錄,不提交

BB@test>select * from test where name='dddd';

NAME
----
dddd

BB@test>delete from test where name='dddd';

1 row deleted.

BB@test>

-- 在會話1中,創建索引,索引的字段寫錯,導致創建失敗

BB@test>create index idx_test_name1 on test(name1);
create index idx_test_name1 on test(name1)
                                    *
ERROR at line 1:
ORA-00904: "NAME1": invalid identifier


BB@test>

-- 在會話2中,查看test表的數據,發現'dddd'那行,已經被提交了。說明ddl即使失敗了,也會提交。也說明了ddl語句,是先commit,再執行ddl語句的。

SYS@test>select * from bb.test;

NAME
----
aaaa

bbbb

cccc

SYS@test>

參考文檔:

關於AUTHID語句

https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/subprograms.htm#LNPLS00809

Using Invoker's Rights or Definer's Rights (AUTHID Clause)

The AUTHID property of a stored PL/SQL unit affects the name resolution and privilege checking of SQL statements that the unit issues at run time. The AUTHID property does not affect compilation, and has no meaning for units that have no code, such as collection types.

AUTHID property values are exposed in the static data dictionary view *_PROCEDURES. For units for which AUTHID has meaning, the view shows the value CURRENT_USER or DEFINER; for other units, the view shows NULL.

For stored PL/SQL units that you create or alter with the following statements, you can use the optional AUTHID clause to specify either CURRENT_USER or DEFINER. The default is DEFINER.

A unit whose AUTHID value is CURRENT_USER is called an invoker's rights unit, or IR unit. A unit whose AUTHID value is DEFINER is called a definer's rights unit, or DR unit. An anonymous block always behaves like an IR unit. A trigger or view always behaves like a DR unit.

The AUTHID property of a unit determines whether the unit is IR or DR, and it affects both name resolution and privilege checking at run time:

  • The context for name resolution is CURRENT_SCHEMA.

  • The privileges checked are those of the CURRENT_USER and the enabled roles.

When a session starts, CURRENT_SCHEMA has the value of the schema owned by SESSION_USER, and CURRENT_USER has the same value as SESSION_USER. (To get the current value of CURRENT_SCHEMA, CURRENT_USER, or SESSION_USER, use the SYS_CONTEXT function, documented in Oracle Database SQL Language Reference.)

另外,在查詢dba_procedures的時候,發現有裏面有個觸發器,查了下官方文檔,觸發器也是存儲過程的一種。

參考文檔:

https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-triggers.html#GUID-3CD2CC67-5AC2-4DD5-B7D3-12E5FAE082C9

9.1 Overview of Triggers

Like a stored procedure, a trigger is a named PL/SQL unit that is stored in the database and can be invoked repeatedly. Unlike a stored procedure, you can enable and disable a trigger, but you cannot explicitly invoke it.

While a trigger is enabled, the database automatically invokes it—that is, the trigger fires—whenever its triggering event occurs. While a trigger is disabled, it does not fire.

You create a trigger with the CREATE TRIGGER statement. You specify the triggering event in terms of triggering statements and the item on which they act. The trigger is said to be created on or defined on the item, which is either a table, a view, a schema, or the database. You also specify the timing point, which determines whether the trigger fires before or after the triggering statement runs and whether it fires for each row that the triggering statement affects. By default, a trigger is created in the enabled state.

If the trigger is created on a table or view, then the triggering event is composed of DML statements, and the trigger is called a DML trigger.

 

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章