【问题标题】:PL/SQL - Insert command doesn't execute in EXCEPTION blockPL/SQL - 插入命令不在 EXCEPTION 块中执行
【发布时间】:2014-12-02 19:37:43
【问题描述】:

我在 PL/SQL 中有这个函数,我想返回给定员工的薪水。此外,我想在每次函数执行时在我创建的表中插入值。问题是该函数在没有错误执行时插入值,但在进入EXCEPTION 块时不插入。我在编译时没有收到任何错误,它只是不执行插入。

CREATE OR REPLACE FUNCTION f(
    v_name employees.last_name%TYPE DEFAULT 'Bell')
  RETURN NUMBER
IS
  v_salary       employees.salary%type;
  v_user         my_info.user%type;
  v_data         my_info.data%type;
  v_command      my_info.command%type := 'f';
  v_no_lines     my_info.no_lines%type;
  v_error        my_info.error%type;
BEGIN
  SELECT USER INTO v_user FROM DUAL;
  SELECT SYSDATE INTO v_data FROM DUAL;
  SELECT SALARY INTO v_salary FROM employees WHERE last_name = v_name;
  v_no_lines := SQL%ROWCOUNT;
  INSERT INTO my_info VALUES(v_user, v_data, v_command, v_no_lines, 'No error'); 
  RETURN v_salary;

EXCEPTION
WHEN NO_DATA_FOUND THEN
    v_no_lines := SQL%ROWCOUNT;
    v_error := 'No employees with given name';
    INSERT INTO my_info VALUES(v_user, v_data, v_command, v_no_lines, v_error); --doesn't make the insert
    RAISE_APPLICATION_ERROR(-20000, 'No employees with given name');  
WHEN TOO_MANY_ROWS THEN 
    v_no_lines := SQL%ROWCOUNT;
    v_error := 'More than one employee with given name';
    INSERT INTO my_info VALUES(v_user, v_data, v_command, v_no_lines, v_error); --doesn't make the insert
    RAISE_APPLICATION_ERROR(-20001, 'More than one employee with given name');

WHEN OTHERS THEN
  RAISE_APPLICATION_ERROR(-20002,'Other error!');
END f;
/ 

稍后编辑

我终于设法进行了插入,但只有在我执行了该功能之后。 我修改了函数并从中删除了所有插入,并使其返回薪水 + 受影响的行数

DECLARE
  v_user         my_info.user%type;
  v_data         my_info.data%type;
  v_command      my_info.command%type := 'f';
  v_no_lines     my_info.no_lines%type;
  v_error        my_info.error%type;
BEGIN 
  SELECT USER INTO v_user FROM DUAL;
  SELECT SYSDATE INTO v_data FROM DUAL;

  DBMS_OUTPUT.PUT_LINE(f('Bad Input', v_no_lines));
  v_error := 'No error';
  INSERT INTO my_info VALUES(v_user, v_data, v_command, v_no_lines, v_error);

  EXCEPTION
  WHEN OTHERS THEN
    v_no_lines := 0;
    v_error := SQLERRM;
    INSERT INTO my_info VALUES(v_user, v_data, v_command, v_no_lines, v_error);
END;
/

【问题讨论】:

  • 它会去哪个异常块?还要添加 dbms_output.put_line('Error : ' || dbms_utility.format_error_backtrace); dbms_output.put_line('错误:'|| dbms_utility.format_error_stack);找出哪行代码给你错误
  • 我看到的第一个问题是,您正试图在您的异常中插入同一个表,而您正试图在主体块中插入该表。如果在初始插入时发生异常,则在您的异常块上将发生相同的异常。你确定它没有进入 OTHERS 捕获?
  • 在运行匿名块之前,数据库会标记一个隐式保存点。如果语句失败,数据库将回滚到保存点。因此,如果异常一直传播到函数中所有未提交的插入语句,包括异常块中的语句,都将被回滚。如果您希望记录异常的详细信息,您可能希望查看带有 PRAGMA AUTONOMOUS_TRANSACTION 的单独过程。
  • @Shankar 感谢您的提示,将使用它。
  • @DrabJay 我尝试使用它,但无法使其工作。还是谢谢。

标签: sql oracle plsql


【解决方案1】:

试试这个方法

DECLARE
  v_user         my_info.user%type;
  v_data         my_info.data%type;
  v_command      my_info.command%type := 'f';
  v_no_lines     my_info.no_lines%type;
  v_error        my_info.error%type;
  v_need_insert  number;
BEGIN
  begin
    v_need_insert := 0;
    SELECT USER INTO v_user FROM DUAL;
    SELECT SYSDATE INTO v_data FROM DUAL;

    DBMS_OUTPUT.PUT_LINE(f('Bad Input', v_no_lines));
    v_error := 'No error';
    INSERT INTO my_info VALUES(v_user, v_data, v_command, v_no_lines, v_error);

    EXCEPTION
    WHEN OTHERS THEN
      v_no_lines := 0;
      v_error := SQLERRM;
      v_need_insert := 1;
    END;
  IF v_need_insert = 1 THEN
    INSERT INTO my_info VALUES(v_user, v_data, v_command, v_no_lines, v_error);
  END IF;
END;

【讨论】:

    【解决方案2】:

    在插入语句后的 EXCEPTION 块内使用 COMMIT。它会起作用

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 2013-08-24
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多