使用Execute Immediate两次执行具有sys对象的Dynamic查询

时间:2016-01-12 19:16:04

标签: sql plsql oracle11g

我有一个字符串,它从过程调用中动态保存查询。 查询是从SYS对象中选择数据,如dba _ *

使用execute immediate调用字符串时,无法使用execute immediate或Open游标打开查询。任何启用此功能的选项,因为我无法从DBA到模式的sys对象上获得批准。

下面是我的代码中如何使用两个执行立即语句来访问SYS对象的示例。

create or replace procedure exp_11 authid current_user as
v_query1 varchar2(100):='select count(1) from dba_objects';
v_query2 varchar2(100):='execute immediate TXT';
v_res number;
v_txt varchar2(100);
begin
v_txt:='select count(1) from dba_objects';
execute immediate v_query1 into v_res;
dbms_output.put_line(v_res);
--This will work with execute immediate directly calling the select statement from dba_objects

v_query2:=replace(v_query2,'TXT',v_txt);
execute immediate v_query2 into v_res;
--This will not work
dbms_output.put_line(v_res);
end;
/

1 个答案:

答案 0 :(得分:1)

authid current_user 用于执行具有当前用户权限的过程(而不是使用创建过程的用户的权限),因此如果您使用的用户没有SELECT权限(或其他所需的权限)在DBA表上,没有办法让它工作。

如果可能,您可以在具有这些权限的用户(如SYS)拥有的模式中执行此过程,并在没有“authid current_user”的情况下执行此过程,为过程创建公共同义词并向需要它的用户授予执行权限。这种方式过程可以访问它的架构所有者拥有的任何内容,并且执行过程的用户不会有权限问题。

也就是说,如果 v_query1 的第一部分有效,并且您可以执行它,那么这不是权限问题。无论有没有立即执行,权限都是一样的。您的程序无效,因为此行不正确:

v_query2:=replace(v_query2,'TXT',v_txt);

您正在替换查询中的“TXT”:

'execute immediate TXT';

使用v_txt:

v_txt:='select count(1) from dba_objects';

所以你的SQL语句最终是:

execute immediate 'execute immediate select count(1) from dba_objects' into v_res;

这是无效的。你不能两次使用execute immediate! (查看有关语法here)的更多信息。

你说你需要动态定义查询,但为什么需要在其中加入'execute immediate'?为什么不在没有它的情况下定义它们呢?

create or replace procedure exp_11 authid current_user as
    v_query2 varchar2(100);
begin
    v_query2 :='select count(1) from dba_objects';
    execute immediate v_query2 into v_res;
    dbms_output.put_line(v_res);
end;
/