【问题标题】:Oracle procedure works only when set serveroutput on;Oracle 过程仅在将 serveroutput 设置为 on 时才起作用;
【发布时间】:2016-09-30 01:14:15
【问题描述】:

尝试使用存储过程插入记录的奇怪行为。 仅适用于set serveroutput on

谢谢。

SQL*Plus: Release 11.2.0.1.0 Production on Tue May 31 22:48:25 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

SQL> exec abc_utils.abc_init(p_table_name => 'ABC_TEST', p_batch_alias => 'TST');
BEGIN abc_utils.abc_init(p_table_name => 'ABC_TEST', p_batch_alias => 'TST'); END;

*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "TESTUSR.abc_utils", line 1743
ORA-06512: at line 1


SQL> set serveroutput on;
SQL> exec abc_utils.abc_init(p_table_name => 'ABC_TEST', p_batch_alias => 'TST');

PL/SQL procedure successfully completed.


    PROCEDURE abc_init(p_table_name    IN VARCHAR2,
                           p_batch_alias   IN VARCHAR2) IS

    v_sql                VARCHAR2(32000);

    --object caller variables
    v_owner              VARCHAR2(30 CHAR);
    v_obj_name           VARCHAR2(30 CHAR);
    v_line_no            NUMBER;
    v_caller_type        VARCHAR2(30 CHAR);
    v_caller             VARCHAR2(4000 CHAR);


    BEGIN
     owa_util.who_called_me(v_owner, v_obj_name, v_line_no, v_caller_type);
       v_caller := 'Object Name: ' || $$plsql_unit || '; Caller Name: ' || v_obj_name || '; Caller Line: ' || to_char(v_line_no);

         --initialise summary table
       v_sql := 'INSERT INTO INIT_SUMMARY (BATCH_ALIAS,TABLE_NAME,START_DT,BATCH_USER,BATCH_RUN) ' ||
                'SELECT a.BATCH_NAME,:1,:2,a.BATCH_USER,:3 FROM INIT_CFG a WHERE 1 = 1 AND BATCH_NAME = :4';

       EXECUTE IMMEDIATE v_sql USING p_table_name,SYSDATE,summary_seq.nextval,p_batch_alias;
       COMMIT;

       EXCEPTION
          WHEN OTHERS THEN
             gv_err_msg := substr('Back Trace: ' ,1,4000);
             RAISE_APPLICATION_ERROR(-20001,'abc_init: ' || gv_err_msg);
    END abc_init;
    --********************************************************************

【问题讨论】:

  • 我希望第 1743 行位于包初始化部分 - 在所有过程和功能之后的包主体中的开始/结束块。每个会话只执行一次,因此第二次调用不会命中它 - 与服务器输出无关。那个块正在做一个选择。请将该部分代码添加到问题中。
  • 顺便说一句,当静态 SQL 绰绰有余,你为什么在这里使用动态 SQL?

标签: oracle stored-procedures oracle11g sqlplus


【解决方案1】:

错误来自package instantiation:

当会话引用包项时,Oracle 数据库会为该会话实例化包。每个引用包的会话都有自己的该包的实例化。

当 Oracle 数据库实例化一个包时,它会对其进行初始化。初始化包括以下任何一项适用: ...

  • 执行包体的初始化部分

该实例化在每个会话中仅发生一次。您对过程的第一次调用将执行初始化部分。第二个电话没有。 set serveroutput on 没有任何效果,只是第二次调用有效,那是因为第二次没有调用初始化。

所以错误来自包体的初始化部分,就在最后——在所有过程和函数等之后。在包的最终end 之前有一个begin。比如:

create or replace package body abc_utils as
  ...
  some_var number; -- package state variable
  ...
  procedure abc_init is
    ...
  begin
    ...
  end abc_init;
  ...
/* package initialisation */
begin
  select some_col into some_var from some_table;  -- line 1743
end abc_utils;
/

该块中的代码将包括第 1743 行,这将是一个 select ... into,它可以找到不止一行。您还没有显示该代码,但您需要调查它。

【讨论】:

  • 确实有一个 Select into 在 Package 的末尾返回多行。非常感谢。
猜你喜欢
  • 2012-10-18
  • 1970-01-01
  • 2018-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多