我有一个字符串,它从过程调用中动态保存查询。 查询是从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;
/
答案 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;
/