我正在编写使用 SqlPlus 运行 sql 脚本的代码。大多数脚本都包含 DDL,这需要 /(正斜杠)来运行缓冲区。有些脚本缺少斜杠。我尝试过运行 @script.sql 等脚本,然后运行 /,但有时它会尝试创建一些内容两次。我也想在最后运行 show error 命令,有时如果 / 丢失,这会给我带来麻烦。
所以,我改为@script。 (句点)显示错误。当文件中存在 / 时,这是有效的,但现在如果文件中缺少 /,如果不创建对象会造成混乱。
我们尝试使用一些逻辑来检查文件中是否以 / 结尾,但在我看来,这是一个混乱的选择。我出现了误报,这不是一个完美的解决方案。
我想过尝试使用另一个工具运行,但由于我工作的公司已经发布了这个工具,并且客户希望它与sqlplus一起运行,并且可能包含仅在sqlplus中工作的命令;不符合 JDBC,我认为这不是一个足够的解决方案。
我现在在想,如果我可以检查 / 是否已在当前缓冲区上运行,并仅在未运行时才执行 / ,那将是一个很好的解决方案,也许是完美的,但我找不到任何此类命令的文档存在。还有其他方法可以解决这个问题吗?这样的命令存在吗? 谢谢!
SQLPlus 非常有限。即使您确定缓冲区是否已发送,也没有控制机制来执行 IF/THEN。
您可以做的一件事是,在运行脚本之前,您调用
exec begin raise login_denied; end;
脚本完成后,调用
#show sqlcode
如果仍然显示 1017(login_denied 的错误代码),那么您可以非常确定该脚本没有执行任何 SQL 语句。如果您愿意,可以使用用户定义的错误代码,例如 raise_application_error(-20123,'dummy');
请注意,我在 show 语句中包含了 # 前缀。运行命令不会影响缓冲区的内容,因此如果您发现没有执行任何内容,您可以尝试使用斜杠运行缓冲区内容。
如果您有一个包含多个 DDL 的脚本(例如一个表加上索引/授权/约束...),那么您仍然面临着不运行最终命令(如果它没有斜杠)的风险。
不要将实际的脚本文件传递给编译器,而是获取脚本文件并将其复制到临时位置。然后,将此文本附加到其末尾:
--If the SQLPlus compiler generates an error here then the
--developer of this file failed to terminate a block of PL/SQL code
--with a required forward slash '/'
SELECT 'SCRIPT FILE TERMINATION CHECK' AS "" FROM DUAL;
SELECT '' FROM DUAL WHERE (1=0);
/
现在,将新的临时文件输入 SQL+ 编译器。
如果原始脚本文件仅包含 SQL(无 PLSQL),那么临时脚本唯一会发生的事情是一些额外的任意、低成本、从双语句中选择。
如果原始脚本文件包含正确分段 (/) SQL 和 PL/SQL 语句的任意组合,则临时脚本唯一会发生的情况是一些额外的任意、低成本、从双语句中选择。
最后,如果原始脚本文件包含任何未正确终止的 PLSQL,则临时脚本每次都会生成错误。