代码之家  ›  专栏  ›  技术社区  ›  bigtunacan

返回事务的成功/失败和错误消息?

  •  0
  • bigtunacan  · 技术社区  · 7 年前

    我需要将更新和插入包装到一个事务中,该事务将从外部web应用程序调用。当调用它时,我试图返回一个基本的成功/失败状态,如果失败,还会显示一条错误消息。

    “SQLCODE”:无效标识符

    DECLARE STATUS VARCHAR2(128); 
        MESSAGE VARCHAR2(128);
    BEGIN
        UPDATE MYTABLE
        SET COL1 = 400
        WHERE USERNAME = 'bigtunacan' AND pk = 12345;
          
        INSERT INTO MYTABLE (username, col1, col2)
                VALUES('bigtunacan', 400, 'foo');
    
        SELECT 'TRUE' AS STATUS, '' AS MSG FROM MYTABLE WHERE ROWNUM = 1;
    
        COMMIT;
    EXCEPTION
        WHEN OTHERS THEN
                ROLLBACK;
                SELECT 'FALSE' AS STATUS, SQLCODE || SQLERRM AS MSG FROM MYTABLE WHERE ROWNUM = 1;
    END;
    
    2 回复  |  直到 5 年前
        1
  •  1
  •   Barbaros Özhan    7 年前

    PL/SQL代码中的任何Select语句都需要INTO子句,从游标调用或在游标内调用的语句除外。在本例中,您不需要调用任何Select语句,只需分配静态字符串值('TRUE','FALSE')或独立于SQL的伪列,例如 sqlcode sqlerrm 添加到已定义的变量。

    因此,考虑使用:

    DECLARE 
        STATUS  VARCHAR2(128) := 'TRUE';  
        MESSAGE VARCHAR2(128);
    BEGIN
        UPDATE MYTABLE
        SET COL1 = 400
        WHERE USERNAME = 'bigtunacan' AND pk = 12345;
    
        INSERT INTO MYTABLE (username, col1, col2)
                VALUES('bigtunacan', 400, 'foo');
    
       -- SELECT 'TRUE' AS STATUS, '' AS MSG FROM MYTABLE WHERE ROWNUM = 1;
       -- completely remove this above row, STATUS is already initialized as TRUE
        COMMIT;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        STATUS := 'FALSE'; 
        RAISE_APPLICATION_ERROR(-20333,'Caution : An error was encountered - 
                                      '||SQLCODE||' -ERROR- '||SQLERRM);
    
    END;
    
        2
  •  0
  •   Kaushik Nayak    7 年前

    理想情况下,提交/回滚不应包含在被调用的过程中。从…起 Tom Kyte's 用自己的话说:

    我希望PLSQL不支持提交/回滚。我坚信事务控制必须在调用程序级别的最顶层完成。

    您应该考虑将匿名块转换为过程,并在调用程序的代码中定义事务控制。

    CREATE OR REPLACE procedure yourprocedure 
    (      p_status  OUT VARCHAR2,
           p_message OUT VARCHAR2
           ) AS
    
    BEGIN
      UPDATE mytable
        SET
         col1 = 400
          WHERE username = 'bigtunacan' AND pk = 12345;
    
    INSERT INTO MYTABLE (username, col1, col2)
                VALUES('bigtunacan', 400, 'foo');
    
         p_status  := 'TRUE' ; 
         p_message := NULL;
    
    EXCEPTION
        WHEN OTHERS THEN
         p_status  := 'FALSE' ; 
         p_message := SQLERRM ;
    END;
    /
    

    调用 (可以是另一个块、过程或应用层)

    DECLARE
         l_status    VARCHAR2(20);
         l_message   VARCHAR2(400);
    BEGIN
         yourprocedure(l_status,l_message);
    
         IF
              l_status = 'TRUE'
         THEN
              COMMIT;
         ELSE
              ROLLBACK;
         END IF;
    END;
    /
    

    Autonomous 过程(主要用于日志记录),您应该在该过程中提交。

    推荐文章