暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 复制 (插入选择) 语句可以在线工作,但不能在过程中立即执行

askTom 2017-03-30
233

问题描述

这是一个老问题,设置是经典的,因此令我惊讶的是我无法使其正常工作。
根据其他帖子,它应该。

用户XX在模式A和B中的表tdata上选择授予。
GRANT SELECT ON A.tdata TO XX;
GRANT SELECT ON B.tdata TO XX;


用户XX已在架构B中的过程copy_data上执行grant。

CREATE OR REPLACE PACKAGE B.PKG AS
  PROCEDURE copy_data;
END PKG;
/
GRANT EXECUTE ON B.PKG TO XX;

CREATE OR REPLACE PACKAGE BODY B.PKG AS
PROCEDURE copy_data IS
  sqlStmt VARCHAR2(4000);
BEGIN
  sqlStmt := 'INSERT INTO B.tdata SELECT * from A.tdata';
  EXECUTE IMMEDIATE sqlStmt;
  EXCEPTION
    WHEN OTHERS THEN
      raise_application_error( -20001, sqlStmt || ' failed with [' || SQLERRM || ']' );
END;
END PKG;
/
GRANT EXECUTE ON B.PKG TO XX;


现在发生的是 (连接为XX):

SQL> INSERT INTO B.tdata SELECT * from A.tdata;

165 rows created.

SQL> exec B.PKG.copy_data;

BEGIN B.PKG.copy_data; END;

*
ERROR at line 1:
ORA-20001: INSERT INTO B.tdata SELECT * from A.tdata failed with [ORA-00942: table or view does not exist]
ORA-06512: at "B.PKG", line 5
ORA-06512: at line 1


我看不到缺少哪些赠款或角色,因此该副本可以像在线一样从程序内部成功。
毕竟,用户XX被授予B.PKG.copy_data (通过包) 的过程执行,用户XX被授予从A.tdata中选择并插入到B.tdata中。

欢迎任何提示。如果我错过了一些非常明显的东西,我很抱歉。

专家解答

您尚未指定在执行包时使用哪些权限 (缺少authid子句)。

这意味着默认情况下,您拥有definer的权利。所以包以所有者的特权执行。B拥有包裹。

所以当你从XX打电话给B.PKG时,it runs with B's privileges。B无法进入A的表!

这就是你的SQL语句工作的原因。以XX的特权运行。

要克服这一点,要么你需要:

-在A.tdata或
-将包声明为 “authid current_user”。这意味着它与invoker的权利一起运行。即在这种情况下的XX:

grant create session, unlimited tablespace to a identified by a;
grant create session, unlimited tablespace to b identified by b;
grant create session  to xx identified by xx;

create table a.tdata (
  x int
);

insert into a.tdata values (1);
commit;

create table b.tdata (
  x int
);
grant select on a.tdata to xx;
grant select, insert on b.tdata to xx;

CREATE OR REPLACE PACKAGE B.PKG authid current_user AS
  PROCEDURE copy_data;
END PKG;
/
GRANT EXECUTE ON B.PKG TO xx;

CREATE OR REPLACE PACKAGE BODY B.PKG AS
PROCEDURE copy_data IS
  sqlStmt VARCHAR2(4000);
BEGIN
  sqlStmt := 'INSERT INTO B.tdata SELECT * from A.tdata';
  EXECUTE IMMEDIATE sqlStmt;
END;
END PKG;
/

conn xx/xx
exec b.pkg.copy_data;

select * from b.tdata;

X  
1 

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论