存储过程权限及存储过程中的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

发布了754 篇原创文章 · 获赞 31 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/xxzhaobb/article/details/102702873
今日推荐