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 的设计模式?的主要内容,如果未能解决你的问题,请参考以下文章