【问题标题】:oracle declare user defined exceptionoracle 声明用户定义的异常
【发布时间】:2012-07-26 11:43:45
【问题描述】:

Oracle SP 未编译

我在 MS SQL 方面有经验,但在 Oracle 上上课,我一生都无法弄清楚为什么这个存储过程的脚本不起作用。我在第一个异常变量的变量声明部分中遇到错误。这是错误消息:

 PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
 in out <an identifier> <a double-quoted delimited-identifier> LONG_ double ref char
 time timestamp interval date binary national character nchar

代码

CREATE or REPLACE Procedure Movie_Rental_SP
(
Mv_ID IN Number,
Mem_ID IN Number,
Pay_ID IN Number,
Mv_Chk Number,
Mem_Chk Number,
Pay_Chk Number,
Qty_Chk Number,
--> next line is where the error points
      UnKnown_Mv Exception,
UnKnown_Mem Exception,
UnKnown_Pay Exception,
UnAvail_Mv Exception    )

IS

BEGIN
SELECT COUNT(Movie_ID) INTO Mv_Chk FROM MM_Movie WHERE Movie_ID = Mv_ID; 
SELECT COUNT(Member_ID) INTO Mem_Chk FROM MM_Member WHERE Member_ID = Mem_ID;
SELECT COUNT(Payment_Methods_ID) INTO Pay_Chk FROM MM_Pay_Type WHERE Payment_Methods_ID = Pay_ID;
SELECT Movie_Qty INTO Qty_Chk FROM MM_Movie WHERE Movie_ID = Mv_ID;

IF       Mv_Chk = 0 THEN RAISE UnKnown_Mv;
ELSE IF Mem_Chk = 0 THEN RAISE UnKnown_Mem;
ELSE IF Pay_Chk = 0 THEN RAISE UnKnown_Pay;
ELSE    Qty_Chk = 0 THEN RAISE UnAvail_Mv;
END IF; 

    DECLARE New_ID NUMBER;
    BEGIN
        SELECT Max(Rental_ID)+1 INTO New_ID FROM MM_Rental;
        EXCEPTION WHEN NO_DATA_FOUND THEN
            New_ID := 1;
            DBMS_OUTPUT.PUT_LINE ('There are no exsisting Rental IDs, ID set to 1');
    END;

INSERT INTO MM_Rental VALUES (New_ID,Mem_ID,Mv_ID,Sysdate,Null,Pay_ID);
UPDATE MM_Movie SET Movie_Qty = Movie_Qty - 1 WHERE Movie_ID = Mv_ID;

EXCEPTION 
    WHEN UnKnown_Mv THEN 
        RAISE_APPLICATION_ERROR(-20001,'There is no movie with Movie ID of: '||Mv_ID||' Transaction cancelled.');
    WHEN UnKnown_Mem THEN 
        RAISE_APPLICATION_ERROR(-20002,'No member exists with member ID: '||Mem_ID||' Transaction cancelled.');
    WHEN UnKnown_Pay THEN
        RAISE_APPLICATION_ERROR(-20003,'No payment type for: '||Pay_ID||' Transaction cancelled.');
    WHEN UnAvail_Mv THEN
        RAISE_APPLICATION_ERROR(-20004,'No movies available for: '||Mv_ID||' Transaction cancelled.');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE ('Error number: '||sqlcode);
        DBMS_OUTPUT.PUT_LINE ('Error message: '||sqlerrm);
        DBMS_OUTPUT.PUT_LINE('Unanticipated error.  Contact your system administrator.');
END;
/

任何帮助将不胜感激!

【问题讨论】:

    标签: oracle


    【解决方案1】:

    我的假设是,在三个IN 参数之后,您的意图是将其他所有内容声明为局部变量,而不是过程的参数。将异常传递给过程是没有意义的。您的“ELSE IFalso needs to beELSIF”。

    CREATE or REPLACE Procedure Movie_Rental_SP
    (
      Mv_ID IN Number,
      Mem_ID IN Number,
      Pay_ID IN Number
    )
    AS
      Mv_Chk Number;
      Mem_Chk Number;
      Pay_Chk Number;
      Qty_Chk Number;
      UnKnown_Mv Exception;
      UnKnown_Mem Exception;
      UnKnown_Pay Exception;
      UnAvail_Mv Exception;  
    BEGIN
      SELECT COUNT(Movie_ID) INTO Mv_Chk FROM MM_Movie WHERE Movie_ID = Mv_ID; 
      SELECT COUNT(Member_ID) INTO Mem_Chk FROM MM_Member WHERE Member_ID = Mem_ID;
      SELECT COUNT(Payment_Methods_ID) INTO Pay_Chk FROM MM_Pay_Type WHERE Payment_Methods_ID = Pay_ID;
      SELECT Movie_Qty INTO Qty_Chk FROM MM_Movie WHERE Movie_ID = Mv_ID;
    
      IF    Mv_Chk = 0 THEN RAISE UnKnown_Mv;
      ELSIF Mem_Chk = 0 THEN RAISE UnKnown_Mem;
      ELSIF Pay_Chk = 0 THEN RAISE UnKnown_Pay;
      ELSE  Qty_Chk = 0 THEN RAISE UnAvail_Mv;
      END IF; 
    
      DECLARE 
        New_ID NUMBER;
      BEGIN
        SELECT Max(Rental_ID)+1 INTO New_ID FROM MM_Rental;
      EXCEPTION WHEN NO_DATA_FOUND THEN
         New_ID := 1;
         DBMS_OUTPUT.PUT_LINE ('There are no exsisting Rental IDs, ID set to 1');
      END;
    
      INSERT INTO MM_Rental VALUES (New_ID,Mem_ID,Mv_ID,Sysdate,Null,Pay_ID);
      UPDATE MM_Movie SET Movie_Qty = Movie_Qty - 1 WHERE Movie_ID = Mv_ID;
    EXCEPTION 
      WHEN UnKnown_Mv THEN 
         RAISE_APPLICATION_ERROR(-20001,'There is no movie with Movie ID of: '||Mv_ID||' Transaction cancelled.');
      WHEN UnKnown_Mem THEN 
          RAISE_APPLICATION_ERROR(-20002,'No member exists with member ID: '||Mem_ID||' Transaction cancelled.');
      WHEN UnKnown_Pay THEN
          RAISE_APPLICATION_ERROR(-20003,'No payment type for: '||Pay_ID||' Transaction cancelled.');
      WHEN UnAvail_Mv THEN
          RAISE_APPLICATION_ERROR(-20004,'No movies available for: '||Mv_ID||' Transaction cancelled.');
      WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE ('Error number: '||sqlcode);
          DBMS_OUTPUT.PUT_LINE ('Error message: '||sqlerrm);
          DBMS_OUTPUT.PUT_LINE('Unanticipated error.  Contact your system administrator.');
    END;
    /
    

    作为一般原则,不重新引发异常的WHEN OTHERS 异常处理程序几乎可以肯定是错误。将数据写入dbms_output 并不能以任何方式保证任何人都可以看到数据或将数据保存在任何地方。所以,例如

      WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE ('Error number: '||sqlcode);
          DBMS_OUTPUT.PUT_LINE ('Error message: '||sqlerrm);
          DBMS_OUTPUT.PUT_LINE('Unanticipated error.  Contact your system administrator.');
          RAISE;
    

    将重新抛出之前引发的任何异常。当然,如果您只是没有捕获您无法处理的异常,您会得到相同的行为。

    【讨论】:

    • 贾斯汀,哇......我写了很多 MS SQL sp,应该已经看到了。谢谢!我当然同意您对 dbms_output 的看法。 WHEN OTHERS 重新提出异常是什么意思?
    • @JesseRightler - 我用重新抛出异常的示例更新了我的答案。
    猜你喜欢
    • 2023-03-29
    • 2013-06-11
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    • 2017-08-26
    • 2016-10-07
    相关资源
    最近更新 更多