检查INSERT是否成功

时间:2009-12-27 10:00:40

标签: oracle

我有一些执行INSERT语句的过程:

CREATE OR REPLACE PROCEDURE potok_insert(
  p_jfplate IN potok.jfplate%TYPE,
  p_post IN potok.post%TYPE,
  p_jfchan IN potok.jfchan%TYPE,
  p_jfdatetime IN VARCHAR2 
  ) 
AS 
  t_jfdatetime TIMESTAMP:=TO_TIMESTAMP(p_jfdatetime,'DD.MM.YYYY HH24:MI:SS');
BEGIN
  INSERT INTO potok (jfplate, post, jfchan, jfdate_y, jfdate_m, jfdate_d, jftime, jfdatetime, 
    dt_reg, ibd_arx)
      VALUES (RTRIM(p_jfplate),
        p_post, 
        RTRIM(p_jfchan), 
        EXTRACT(YEAR FROM t_jfdatetime), 
        EXTRACT(MONTH FROM t_jfdatetime), 
        EXTRACT(DAY FROM t_jfdatetime), 
        LPAD(EXTRACT(HOUR FROM t_jfdatetime),2,'0')||':'||
        LPAD(EXTRACT(MINUTE FROM t_jfdatetime),2,'0')||':'||
        LPAD(EXTRACT(SECOND FROM t_jfdatetime),2,'0'), 
        CAST(t_jfdatetime AS DATE),
        SYSDATE,
        1);  
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK;
END potok_insert;

有些触发器和约束适用于表,它们可以 INSERT。 我如何检查程序正文 - 如果INSERT成功与否?

当然我可以在头部和程序结束时调用count(),但这不是那么优雅的解决方案。

5 个答案:

答案 0 :(得分:7)

您可以使用RETURNING子句返回刚刚创建的行的rowid,如下所示:

CREATE SEQUENCE seq_emp;

set serveroutput on

DECLARE
 x emp.empno%TYPE;
BEGIN
  INSERT INTO emp
  (empno, ename)
  VALUES
  (seq_emp.NEXTVAL, 'Morgan')
  RETURNING empno
  INTO x;

  dbms_output.put_line(x);
END;
/

DECLARE
 r rowid;
BEGIN
  INSERT INTO emp
  (empno, ename)
  VALUES
  (seq_emp.NEXTVAL, 'Morgan')
  RETURNING rowid
  INTO r;

  dbms_output.put_line(r);
END;
/

DECLARE
 x emp.empno%TYPE;
 r rowid;
BEGIN
  INSERT INTO emp
  (empno, ename)
  VALUES
  (seq_emp.NEXTVAL, 'Morgan')
  RETURNING rowid, empno
  INTO r, x;

  dbms_output.put_line(r); 
  dbms_output.put_line(x);
END;

取自此链接:

http://www.psoug.org/reference/insert.html

答案 1 :(得分:6)

删除EXCEPTION ......等等。

真的问题不应该是如何测试以确定它是否成功,而是决定如果失败该怎么做。

答案 2 :(得分:2)

当违反约束时,将抛出异常并且您将最终进入异常处理块。

哪种触发器阻止您插入?你也可以在那里抛出异常吗?

答案 3 :(得分:1)

在异常块中,您应该转储SQLCODE和SQLERRM的内容,以便查看您获得的错误。也许在你的WHEN OTHERS处理程序中添加以下内容会有所帮助:

DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE ||
                     '  SQLERRM=''' || SQLERRM || '''');

分享并享受。

答案 4 :(得分:1)

您可以检查 SQL%ROWCOUNT 的值,以确定是否实际插入了一行。我认为在没有引发异常的情况下触发未能(或决定不)插入记录的触发器将是非常糟糕的做法,但它可能会发生。

另外,你的“回滚”;声明是多余的,应该改为这样:

EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE ||
                     '  SQLERRM=''' || SQLERRM || '''');
RAISE;
END;

RAISE 命令将引发从触发器捕获的相同异常,以便您的调用程序知道它失败的原因(除了调试dbms_output之外)。