Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Oracle';中使用OUT参数捕获错误;s程序_Oracle_Stored Procedures_Plsql_Oracle11g - Fatal编程技术网

在Oracle';中使用OUT参数捕获错误;s程序

在Oracle';中使用OUT参数捕获错误;s程序,oracle,stored-procedures,plsql,oracle11g,Oracle,Stored Procedures,Plsql,Oracle11g,我必须创建将行插入表的过程,还需要包括将捕获任何错误的am OUT参数。然而,当我使用匿名块进行测试时,它不会工作,但若我在过程中使用exception,它就会工作。这意味着,如果我添加一个OUT参数并从块中传递值,它将不起作用 此代码有效,但不是我想要的: create or replace PROCEDURE EXAM_SP (P_FIRSTNAME IN BB_SHOPPER.FIRSTNAME%TYPE, P_LASTNAME IN BB_SHOPPER.LAST

我必须创建将行插入表的过程,还需要包括将捕获任何错误的am OUT参数。然而,当我使用匿名块进行测试时,它不会工作,但若我在过程中使用exception,它就会工作。这意味着,如果我添加一个OUT参数并从块中传递值,它将不起作用

此代码有效,但不是我想要的:

    create or replace 
    PROCEDURE EXAM_SP 
(P_FIRSTNAME IN BB_SHOPPER.FIRSTNAME%TYPE,
 P_LASTNAME  IN BB_SHOPPER.LASTNAME%TYPE,
 P_ADDRESS IN BB_SHOPPER.ADDRESS%TYPE,
 P_CITY IN BB_SHOPPER.CITY%TYPE,
 P_STATE IN BB_SHOPPER.STATE%TYPE,
 P_ZIP IN BB_SHOPPER.ZIPCODE%TYPE)


IS  

BEGIN
INSERT INTO BB_SHOPPER (IDSHOPPER, FIRSTNAME, LASTNAME, ADDRESS, CITY,   
STATE, ZIPCODE)
VALUES                   
(BB_SHOPPER_IDSHOPPER_SEQ.NEXTVAL,P_FIRSTNAME,P_LASTNAME,P_ADDRESS, 
                        P_CITY, P_STATE,P_ZIP);

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error Code = '||SQLCODE); 
DBMS_OUTPUT.PUT_LINE('Error Message = Please check input');     
END EXAM_SP;.   
但在上面的代码中,如果我将参数命名为out,它将不起作用,如果我将out参数添加到过程并传递值,则不确定如何执行此操作:

    create or replace 
    PROCEDURE EXAM_SP 
(P_FIRSTNAME IN VARCHAR2,
 P_LASTNAME  IN VARCHAR2,
 P_ADDRESS IN VARCHAR2,
 P_CITY IN VARCHAR2,
 P_STATE IN CHAR,
 P_ZIP IN VARCHAR2,
 P_ERROR OUT VARCHAR2)......
我将收到此错误

ORA-06502: PL/SQL: numeric or value error: character string buffer too small
如果我删除参数并在开始时使用原始代码,它就会工作

获取该错误的匿名块:

DECLARE
  LV_FIRSTNAME_TXT BB_SHOPPER.FIRSTNAME%TYPE := 'FIRST';
  LV_LASTNAME_TXT BB_SHOPPER.LASTNAME%TYPE := 'LAST';
  LV_ADDRESS_TXT BB_SHOPPER.ADDRESS%TYPE := '8899 TAPE PARK';
  LV_CITY_TXT BB_SHOPPER.CITY%TYPE := 'JACKSONVILLE';
  LV_STATE_TXT BB_SHOPPER.STATE%TYPE := 'FLd';
  LV_ZIP_NUMBER BB_SHOPPER.ZIPCODE%TYPE := '34567';
  LV_ERROR varchar2(100);

BEGIN 
  EXAM_SP(LV_FIRSTNAME_TXT, LV_LASTNAME_TXT, LV_ADDRESS_TXT,      
    LV_CITY_TXT,LV_STATE_TXT,LV_ZIP_NUMBER);

    DBMS_OUTPUT.PUT_LINE(LV_ERROR);
END;
程序:

  create or replace 
  PROCEDURE EXAM_SP 
(P_FIRSTNAME IN VARCHAR2,
 P_LASTNAME  IN VARCHAR2,
 P_ADDRESS IN VARCHAR2,
 P_CITY IN VARCHAR2,
 P_STATE IN CHAR,
 P_ZIP IN VARCHAR2,
 P_ERROR OUT VARCHAR2)



IS  

BEGIN
  INSERT INTO BB_SHOPPER (IDSHOPPER, FIRSTNAME, LASTNAME, ADDRESS, CITY, 
                        STATE, ZIPCODE)
  VALUES                  
         (BB_SHOPPER_IDSHOPPER_SEQ.NEXTVAL,P_FIRSTNAME,P_LASTNAME,P_ADDRESS, 
                        P_CITY, P_STATE,P_ZIP);

EXCEPTION
  WHEN OTHERS THEN
  P_ERROR := SQLCODE;

/*DBMS_OUTPUT.PUT_LINE('Error Code = '||SQLCODE); 
DBMS_OUTPUT.PUT_LINE('Error Message = Please check input'); 
P_ERROR := SQLCODE;*/

END EXAM_SP;
我收到的错误消息:

Error report:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
06502. 00000 -  "PL/SQL: numeric or value error%s"
为了测试错误捕获,我将变量
'FLd'
传递给过程参数

表结构:

IDSHOPPER   NUMBER(4,0)
FIRSTNAME   VARCHAR2(15 BYTE)
LASTNAME    VARCHAR2(20 BYTE)
ADDRESS VARCHAR2(40 BYTE)
CITY    VARCHAR2(20 BYTE)
STATE   CHAR(2 BYTE)
ZIPCODE VARCHAR2(15 BYTE)
PHONE   VARCHAR2(10 BYTE)
FAX VARCHAR2(10 BYTE)
EMAIL   VARCHAR2(25 BYTE)
USERNAME    VARCHAR2(8 BYTE)
PASSWORD    VARCHAR2(8 BYTE)
COOKIE  NUMBER(4,0)
DTENTERED   DATE
PROVINCE    VARCHAR2(15 BYTE)
COUNTRY VARCHAR2(15 BYTE)
...
错误堆栈显示:

ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
06502. 00000 -  "PL/SQL: numeric or value error%s"
该堆栈显示错误来自匿名块的第6行,部分原因是它没有提到过程名称。它还没有到达该块第11行的过程调用的程度

问题是您已经定义了局部状态变量:

LV_STATE_TXT BB_SHOPPER.STATE%TYPE := 'FLd';
使用
%类型
语法,非常好;但是,由于表列是char(2),当您尝试将三字符文本文本
'Fld'
分配给该两字符局部变量时,会立即出错

它还没有将三个字符的值发送到过程,因此您期望从
insert
中得到的错误不会出现,因为
insert
也不会发生

如果您想用该特定错误将其打断,您可以将局部变量声明更改为固定长度,而不是像您通常希望的那样使用
%TYPE

DECLARE
  LV_FIRSTNAME_TXT BB_SHOPPER.FIRSTNAME%TYPE := 'FIRST';
  LV_LASTNAME_TXT BB_SHOPPER.LASTNAME%TYPE := 'LAST';
  LV_ADDRESS_TXT BB_SHOPPER.ADDRESS%TYPE := '8899 TAPE PARK';
  LV_CITY_TXT BB_SHOPPER.CITY%TYPE := 'JACKSONVILLE';
  --LV_STATE_TXT BB_SHOPPER.STATE%TYPE := 'FLd';
  -- specific length to allow invalid value to be used
  LV_STATE_TXT char(3) := 'FLd';
  LV_ZIP_NUMBER BB_SHOPPER.ZIPCODE%TYPE := '34567';
  LV_ERROR varchar2(100);

BEGIN 
  EXAM_SP(LV_FIRSTNAME_TXT, LV_LASTNAME_TXT, LV_ADDRESS_TXT,      
    LV_CITY_TXT,LV_STATE_TXT,LV_ZIP_NUMBER,LV_ERROR);

 DBMS_OUTPUT.PUT_LINE(LV_ERROR);
END;
/

-12899

PL/SQL procedure successfully completed.
或者更简单地直接为IN参数使用文本,因为此时您正在测试过程:

DECLARE
  LV_ERROR varchar2(100);
BEGIN 
  EXAM_SP('FIRST', 'LAST', '8899 TAPE PARK',      
    'JACKSONVILLE', 'FLd', '34567', LV_ERROR);

 DBMS_OUTPUT.PUT_LINE(LV_ERROR);
END;
/

-12899

PL/SQL procedure successfully completed.
您可能会发现返回错误文本更有用,而不仅仅是数字(如果要返回错误数字,请使用数字形式的参数类型!),例如:


当然,正如我在一篇评论中提到的,最好让Oracle的异常处理将实际的异常冒泡到调用方——除了日志记录之外,您应该只捕获实际可以处理的异常。请注意,返回的错误消息不会告诉您代码中发生错误的位置;如果没有异常处理程序,您将在过程中看到包含违规语句的行号。正如APC指出的,每个调用方都必须寻找和处理响应,这很容易被忽略。当然,总会有例外(ha),但这似乎是做错事情的一种练习

“如果我向过程中添加参数并传递值,我将收到此错误”

亚历克斯给出了很长的答案,我只想说一点:这是一个糟糕的做法。大多数编程语言都包含处理异常的内置功能。您的建议会产生两个体系结构问题:

  • 调用您的过程的程序必须编写非标准代码来捕获错误,这对于编写调用程序的开发人员和其他必须了解它们如何工作的人来说都是一件痛苦的事情
  • 您的过程不会抛出异常,因此即使它“失败”,也会将成功状态返回给调用程序。如果编写调用程序的开发人员没有实现特殊代码,则会丢失异常,数据库可能处于无效状态

  • 为什么要使用out参数,而不是让调用方直接看到异常(以及错误堆栈)?不管怎样,不清楚你有什么问题;为什么不向我们显示不起作用的代码以及您在该代码中遇到的错误或问题呢?在本例中,我想返回到anonymous block并打印出来,或者显示给用户作为提示。如果我将参数添加到过程中并通过值,我将收到以下错误:创建或替换过程检查\u SP(P_FIRSTNAME在VARCHAR2中,P_LASTNAME在VARCHAR2中,P_地址在VARCHAR2中,P_城市在VARCHAR2中,P_州在CHAR中,P_ZIP在VARCHAR2中,P_错误在VARCHAR2中)……请显示您的完整新过程和您正在使用的匿名块;以及错误堆栈跟踪,以便我们能够准确地看到引发异常的位置。任何事情都不要使用
    CHAR
    。此外,请避免使用
    SQLCODE
    。非常感谢您的帮助和时间,我对编写过程、函数相对来说比较陌生和/或PKG。在这里和我的工作场所,我还有很长的路要走。再次感谢:)非常感谢您提供的非常详细的答案和帮助,我知道复习和提供有用的指导和建议需要时间。再次非常感谢你!!
    ...
    EXCEPTION
      WHEN OTHERS THEN
        P_ERROR := SQLERRM;
    END EXAM_SP;
    /
    
    -- same anonymous block
    
    ORA-12899: value too large for column "MY_SCHEMA"."BB_SHOPPER"."STATE" (actual: 3, maximum: 2)
    
    PL/SQL procedure successfully completed.