如何在dbms_sql.open_cursor上解决ORA-29471?

时间:2013-12-19 19:41:52

标签: oracle plsql dynamic-sql

我正在使用Oracle 11.2.0.1.0并尝试让dbms_sql包运行。 但是,我一直收到ORA-29471错误,如下所示:

DECLARE
  c INTEGER;
BEGIN
  c := dbms_sql.open_cursor();
END;

ORA-29471: DBMS_SQL access denied
ORA-06512: at "SYS.DBMS_SQL", line 1017
ORA-06512: at line 4

oracle docs说出以下内容:

  

绑定和执行时进行检查。可选地,可以进行检查   为每个单独的DBMS_SQL子程序调用执行。检查是:

     
      
  • 调用子程序时current_user与调用最新解析时的相同。
  •   
  • 调用子程序时启用的角色必须是调用最新解析时已启用角色的超集。
  •   
     

与定义者权利子程序的使用一致,角色没有   应用。如果检查失败,则引发ORA-29470错误。

据我所知,这两个条件都不适用于我的代码,因为代码不会跨越模式。

Oracle support(需要登录)网站建议我将security_level参数显式添加到dbms_sql.open_cursor中。添加任何值(0/1/2)都无法解决问题。

令我感到困惑的是,我在dbms_sql.open_cursor收到错误,这是首次定义安全级别的地方。

支持网站还提出了一个涉及设置的解决方法:

alter system set "_dbms_sql_security_level" = 384 scope=spfile;

我还没试过。我更愿意将其视为最后的手段,因为它涉及禁用安全层,而且它是一个不受支持的oracle功能。生产使用的情况非常理想。此外,它根本没有真正解决问题,只是隐藏它。

如何解决此错误?

2 个答案:

答案 0 :(得分:13)

唯一的原因(目前看不到另一个)为什么您的代码会引发ORA-29471,因为您已经通过提供无效的游标ID使dbms_sql在您的会话中无法运行:

/* dbsm_sql detects invalid cursor ID in this session  */ 
SQL> declare
  2    c_1 number := 5;  -- invalid cursor ID. There is no cursor 
  3    l_res boolean;    -- opened with ID = 5     
  4  begin
  5    l_res := dbms_sql.is_open(c_1);
  6  end;
  7  /
declare
*
ERROR at line 1:
ORA-29471: DBMS_SQL access denied 
ORA-06512: at "SYS.DBMS_SQL", line 1104 
ORA-06512: at line 5 


/* An attempt to execute this simple anonymous PL/SQL block after 
   an invalid cursor ID has already been detected by the dbms_sql 
   in the current session will lead to ORA-29471 error  
*/

SQL> declare
  2    c_2 number;
  3  begin
  4    c_2 := dbms_sql.open_cursor();
  5  end;
  6  /
declare
*
ERROR at line 1:
ORA-29471: DBMS_SQL access denied 
ORA-06512: at "SYS.DBMS_SQL", line 1084 
ORA-06512: at line 4 

尝试在新建立的会话中执行该代码。

答案 1 :(得分:0)

解决方案可能是查看v$Session视图。

如果光标存在于列表中,则表示您仍然可以使用它。然后从sql_id中识别它,你可以检查。在这里生成列表:

  select  sql_id, sql_text, count(*) as "OPEN CURSORS", user_name 
   from v$open_cursor
  where user_name <>'SYS' 
group by sql_text, user_name 
order by count(*) desc;

更多here