【发布时间】: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 我尝试使用它,但无法使其工作。还是谢谢。