【问题标题】:Check for existence of table (or view) before upsert在 upsert 之前检查表(或视图)是否存在
【发布时间】:2016-01-07 05:53:17
【问题描述】:

我正在编写一个部署脚本,其中包含一个 MERGE 到一个视图中,该视图可能存在也可能不存在于许多目标架构之一(架构?架构?)中。

我正在尝试这个 SQL:

DECLARE
BEGIN
    /* MERGE statement that will work if the view is available */
EXCEPTION
    WHEN OTHERS THAN
        DBMS_OUTPUT.put_line('warning: merge target is not available');
END;

当我运行这个块时,我得到标准的“PL/SQL:ORA-00942:表或视图不存在”错误。

如何捕获此错误并生成警告行?

【问题讨论】:

  • 什么是 upsert ?一个心烦意乱的插入?
  • Oracle 编译/解析 pl/sql 块时会出现该错误,因此它实际上并未运行代码。解决此问题的一种方法是将语句写入 varchar2 字符串并使用 EXECUTE IMMEDIATE 运行它,因为这会在运行时而不是在脚本编译时引发异常。

标签: oracle plsql oracle11g


【解决方案1】:

将有效答案与建议的改进相结合,所有这些都结合在一起:

SET SERVEROUTPUT ON;
PROMPT ...trying UPSERT;

DECLARE
    eTableNotExists exception;
    pragma exception_init(eTableNotExists, -00942);
BEGIN
    EXECUTE IMMEDIATE '<MERGE statement that will work if the view is available--no trailing ";"!>';

    DBMS_OUTPUT.put_line('insert worked');

EXCEPTION
    WHEN eTableNotExists THEN
        DBMS_OUTPUT.put_line('FYI: doesn''t exist on this schema');
END;
/

COMMIT;

SET SERVEROUTPUT OFF;

SERVEROUTPUT 集合是查看DBMS_OUTPUT.put_line() 的结果所必需的)

【讨论】:

  • 我建议删除WHEN OTHERS THEN ...。如果出现错误,让 Oracle 使用其默认的错误传播系统,该系统会列出所有错误和行号。对于这个小例子来说,这并不重要,但在实际生产代码中,当捕获到异常并且大部分跟踪信息都丢失时,它会令人愤怒。
【解决方案2】:

你需要使用动态SQL:

BEGIN
    EXECUTE IMMEDIATE 'MERGE ...';
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.put_line('warning: merge target is not available');
END;

【讨论】:

  • 为了安全起见,我会使用实际的 SQLERRM 消息进行陷阱和警告,以防除了表不存在(表锁定、缺少列、数据中的值错误等)之外的其他原因导致问题。 WHEN OTHERS 最好谨慎使用...
  • @MichaelBroughton 是的,我非常同意。
【解决方案3】:

您可以使用动态 SQL 将此类错误推迟到运行时并捕获它

EXECUTE IMMEDIATE '<MERGE>' 

而不是“静态”合并

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    相关资源
    最近更新 更多