我在USER A中有一个对象,用于更新USER B模式中的表。 运行程序包时,它将使用USER B的登录名在Oracle中运行。
USER A无权更新USER B架构中的表。 当我尝试在USER A的模式中编译包时,我得到的权限不足以阻止它编译。</ p>
有没有办法在USER A的架构中编译对象,即使他没有更新USER B表的权限?如果包在USER B的上下文中运行,包是否会正确更新表?
我不想将包放在USER B的架构中。
答案 0 :(得分:2)
你可以。但它可能不是最好的方法。该包需要声明为调用者的权利包。 UPDATE
语句需要使用动态SQL。
在B
SQL> create table b.foo( col1 number );
Table created.
SQL> insert into b.foo values( 1 );
1 row created.
SQL> commit;
Commit complete.
在A
中创建包。请注意,该包声明为authid current_user
,这意味着它依赖于调用用户的特权而不是定义用户的特权。由于A
无法看到表,因此我们使用动态SQL,以便语法检查延迟到运行时
SQL> create package update_foo
2 authid current_user
3 as
4 procedure set_val( p_new_val in number );
5 end;
6 /
Package created.
SQL> ed
Wrote file afiedt.buf
1 create or replace package body update_foo
2 as
3 procedure set_val( p_new_val in number )
4 as
5 begin
6 execute immediate 'update b.foo set col1 = :new_val'
7 using p_new_val;
8 end;
9* end;
SQL> /
Package body created.
SQL> grant execute on update_foo to b;
Grant succeeded.
现在,B
可以执行包并修改数据
SQL> exec a.update_foo.set_val( 2 );
PL/SQL procedure successfully completed.
SQL> select * from foo;
COL1
----------
2
然而,总的来说,这不是一种特别明智的方法。一般而言,在一个模式中使用代码而在另一个模式中使用对象的关键在于提供职责分离和职责分离。如果您必须以可以对表发出UPDATE
的用户身份登录,那么拥有一个包来执行此操作并不会增加太多安全性。在这种情况下,它只是增加了复杂性。