在 Oracle 中执行 DELETE 查询时如何重现异常

Posted

技术标签:

【中文标题】在 Oracle 中执行 DELETE 查询时如何重现异常【英文标题】:How to reproduce exception when performing DELETE query in Oracle 【发布时间】:2015-08-26 09:16:26 【问题描述】:

我想在从 Oracle 数据库中的表执行 DELETE 查询以进行某些测试时重现异常。

但是删除的时候出现异常怎么办呢?

【问题讨论】:

您需要先了解 run time vs compile time 错误。 PL/SQL 异常块将捕获运行时错误,而不是编译时错误。 感谢您指出这一点,但我已经知道了。我的问题是在执行 DELETE 查询时如何发生异常(有多少种方式?),而不是如何处理异常。 您是否在询问 DELETE 语句中出现错误的所有可能性? 答案取决于您想要发生的异常。如果您想要删除零异常,请在查询中包含 where 1/0 = 1。我认为这是您要强制执行的其他一些例外情况。 @ShannonSeverance 是的,通常 DELETE 查询应该运行得很好,我只是认为锁定该 TABLE 可能会强制异常,但还不知道该怎么做。 【参考方案1】:

但是删除的时候出现异常怎么办呢?

请记住,PL/SQL 异常块会捕获运行时错误,而不是编译时错误。

首先在没有任何异常块的情况下执行代码,因此您将获得具有精确行号的整个错误堆栈。

基于完整的错误堆栈,如果您想优雅地处理异常,则创建您的用户定义的异常并在EXCEPTION块中处理它们。 p>

例如,

无异常块

SQL> BEGIN
  2    DELETE FROM emp WHERE loc = 'NEW_YORK';
  3  END;
  4  /
  DELETE FROM emp WHERE loc = 'NEW_YORK';
                        *
ERROR at line 2:
ORA-06550: line 2, column 25:
PL/SQL: ORA-00904: "LOC": invalid identifier
ORA-06550: line 2, column 3:
PL/SQL: SQL Statement ignored

所以,我可以在错误堆栈中看到 ORA-00904 Invalid Identifier 错误。

处理异常

SQL> SET serveroutput ON
SQL> DECLARE
  2    invalid_identifier EXCEPTION;
  3    PRAGMA EXCEPTION_INIT(invalid_identifier, -904);
  4    text VARCHAR2(128);
  5  BEGIN
  6    text:='DELETE FROM emp WHERE loc = ''NEW_YORK''';
  7    EXECUTE immediate text;
  8  EXCEPTION
  9  WHEN invalid_identifier THEN
 10    dbms_output.put_line('Invalid identifier error in delete statement');
 11  END;
 12  /
Invalid identifier error in delete statement

PL/SQL procedure successfully completed.

SQL>

DBMS_OUTPUT 仅用于演示目的,实际上您会记录错误。

【讨论】:

【参考方案2】:

您必须有一个条件,您希望根据该条件引发与业务逻辑相关的异常。但是,如果你想强制引发异常,你可以定义你的异常并像 'raise your_exception' 一样引发它;

【讨论】:

【参考方案3】:
create table test_delete(a varchar2(10));
    insert into test_delete values('abc');
    insert into test_delete values('abc');
    insert into test_delete values('err123');
    insert into test_delete values('err3');

    CREATE OR REPLACE TRIGGER delete_exeption
     BEFORE
      DELETE
     ON test_delete
    REFERENCING NEW AS NEW OLD AS OLD
     FOR EACH ROW
    begin 

     if( INSTR( :old.a, 'err') > 0 ) then
       raise_application_error(-20000,'Error');
     end if;
    end;
    /


    delete from test_delete where a = 'abc'; -- no error
    delete from test_delete where a = 'err123'; -- error

只有在删除列a中包含“err”的行时才会发生错误

【讨论】:

【参考方案4】:

如果我理解正确,您会寻找异常的语义。 这是一个例子:

DECLARE
   pe_ratio NUMBER(3,1);
BEGIN
   SELECT price / earnings INTO pe_ratio FROM stocks
     WHERE symbol = 'XYZ';  -- might cause division-by-zero error
     INSERT INTO stats (symbol, ratio) VALUES ('XYZ', pe_ratio);
   COMMIT;
   EXCEPTION  -- exception handlers begin
   WHEN ZERO_DIVIDE THEN  -- handles 'division by zero' error
   INSERT INTO stats (symbol, ratio) VALUES ('XYZ', NULL);
   COMMIT;
   ...
  WHEN OTHERS THEN  -- handles all other errors
  ROLLBACK;
END;  -- exception handlers and block end here

如您所见,您可以使用预定义的例外或对其他人使用“WHEN OTHER THEN”子句,实际上您可以将它用于所有例外。 实际上,我从以下链接中的 Oracle 文档中复制了这个示例,在这里您还可以找到预定义异常的列表: https://docs.oracle.com/cd/B10500_01/appdev.920/a96624/07_errs.htm

【讨论】:

以上是关于在 Oracle 中执行 DELETE 查询时如何重现异常的主要内容,如果未能解决你的问题,请参考以下文章

oracle undo表空间该如何估算,设计多大合适?

oracle 10g R2数据库,用pl/sql developer 删除数据时,执行DELETE FROM TABLE1后就一直停在执行的状态,

oracle delete 锁

如何在执行查询时自动保存oracle SQL查询?

如何提高oracle的查询速度

执行 DELETE 查询时备份 MySQL