DML 发生后提示用户,然后执行 DDL 的设计模式?

Posted

技术标签:

【中文标题】DML 发生后提示用户,然后执行 DDL 的设计模式?【英文标题】:Design Pattern for Prompting Users after DML occurs, then performing DDLs? 【发布时间】:2018-08-13 14:47:12 【问题描述】:

我正在尝试编写一个可以从 SQLPlus 运行的 PLSQL 脚本,它通常会执行如下操作:

    对几个表执行一些 DML 操作。 提示用户确认在步骤 1 中采取的操作。 确认后,执行提交和一系列 DDL 操作,否则回滚。

理想情况下,我希望减少用户所需的手动输入,并让脚本完成所有工作(包括用户指定时的提交/回滚以及发生错误时的回滚)。

我尝试了以下方法:

    将 DML 和 DDL 分离到各自的 PLSQL 块中。

    问题:

    如果 DML 块中有错误,DDL 块仍会执行。 无法处理我在 SQLPlus 界面中明确引发的自定义错误(即,它只会产生大的 ORA 错误消息,我更愿意捕获它并仅显示自定义字符串消息)。

    将单独的块包装在一个错误处理块中。

    问题:

    失去提示用户输入的能力。

我不可能是第一个想要在 DML 更改后根据用户输入执行 DDL 操作的人。是否有一个既定的模式来尝试执行这一系列操作,或者这是语言无法做到的?

谢谢。

【问题讨论】:

也许您可以保留双块结构,但如果第一个块未设置某些主机变量,则让第二个块不执行任何操作。不过,我不确定您在 SQL*Plus 中引发的这些自定义错误是什么。 PLSQL / SQL* Plus 不擅长模拟用户界面程序,您应该更喜欢任何其他语言来更好地控制此类操作。 嘿,William,我所说的“干净”是指我想捕获错误并只显示自定义消息,而不是繁琐的 ORA 错误消息块。如何从另一个匿名块中引用另一个匿名块中的变量? 您可以使用异常处理程序包装 PL/SQL 块,在其中您可以使用 raise_application_error 将丑陋的 ORA 错误消息与您自己的(也许不那么丑陋的)错误消息进行转换;但我同意 Kaushik 的观点,这可能不是最适合 SQL*Plus 等命令行工具的任务。 【参考方案1】:

您可能应该使用脚本语言来实现复杂的交互逻辑,但在 SQL*Plus 中的两个独立块之间传递信息的一种方法是使用主变量:

set serverout on size 10000
set autoprint off
set feedback off

var status number

begin
    update sometable set somecolumn = 1
    where  whatever = somethingelse;

    :status := 1;
end;
/

begin
    if :status = 1 then
        dbms_output.put_line('The update worked.');
    else
        dbms_output.put_line('Something went wrong.');
    end if;
end;
/

输出:

    update sometable set somecolumn = 1
           *
ERROR at line 2:
ORA-06550: line 2, column 12:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 2, column 5:
PL/SQL: SQL Statement ignored


Something went wrong.

【讨论】:

以上是关于DML 发生后提示用户,然后执行 DDL 的设计模式?的主要内容,如果未能解决你的问题,请参考以下文章

oracle中DDL DML指啥?

oracle中DDL DML指啥?

dljd_(007_008)_jdbc执行DQL/DML/DDL语句

DDL 和 DML 脚本的分离 - Flyway

PL/SQL触发器

什么是DDL与DML