在 PL/SQL 中使用 oracle SET 值

Posted

技术标签:

【中文标题】在 PL/SQL 中使用 oracle SET 值【英文标题】:Use oracle SET values in PL/SQL 【发布时间】:2016-01-14 09:44:11 【问题描述】:

我被要求为迁移文件设置一些环境参数。但是,像SQLBLANKLINES 这样的参数只在sqlplus中有效,其他工具(例如Flyway)会被它的使用破坏。 autocommit 也是如此。

有什么方法可以执行以下操作:

declare
   v1 varchar2(60)
begin
   v1 := SHOW SQLBLANKLINES
   if (v1 is not empty) then
      SET SQLBLANKLINES ON
   end if;
end;
/

或者以某种方式查询环境以设置可用参数?

或者以某种方式确定正在使用的正是 sqlplus?

我知道SHOWSET 命令,但我不知道如何将它们的结果放入变量并在PL/SQL 中调用SET

Oracle 是 11g。

【问题讨论】:

如果您不知道将使用哪个客户端,则应在运行迁移文件之前在客户端环境中设置这些内容。这是安装说明在必要时指定的内容。但是不,您无法查看客户端设置或从 PL/SQL 块运行客户端命令。 【参考方案1】:

您不能在 PL/SQL 中引用 SQL*Plus 命令,因为 PL/SQL 无法识别它们。此外,您不能直接在SQL*Plus 脚本中使用条件语句,因此您必须有点创意。但是,您可以有一个脚本来创建和运行另一个脚本,您可以使用它来注入条件语句。

例如,这是我用来让我的发布脚本继续或不继续的脚本(它退出 SQL*Plus):

continue_or_exit.sql:

prompt Do you want to continue script execution? 

accept yn prompt 'Y / N :  ';
set termout off;
set verify off;
set heading off;
set pause off;
set echo off;
column aaaa newline;

spool continue_or_exit_output.sql

select decode(upper('&&yn'), 'Y', 'prompt Executing ...',
                                  'prompt Stopped'
              ),
       decode(upper('&&yn'), 'Y', '', 'accept return_key prompt ''Press <Return>''') aaaa,
       decode(upper('&&yn'), 'Y', '', 'exit') aaaa
from dual;

spool off;
set termout on;

@continue_or_exit_output.sql

set termout on;
set verify on;
set heading on;

您应该能够根据您的情况对其进行修改,以决定是否打印出相关的 SQL*plus 命令。

【讨论】:

看起来不错,但这个脚本是交互式的,但我想通过 Flyway 手动和自动运行它 您不必以交互方式定义变量;您可以在调用它时将其作为脚本的一部分传递。例如。 @your_release_scripts your_param_value,然后通过&amp;&amp;1 引用它。这样,您可以在调用时定义它,希望您可以在 Flyway 中这样做? 其实flyway只是简单的获取带有特定前缀的文件列表,然后一个一个地执行。 那么也许您可以创建包装脚本,只需使用正确的参数调用相关脚本?【参考方案2】:

您不能从 PL/SQL 中调用 SQL*Plus 或任何客户端命令。它完全在服务器上执行。您可以告诉which client is being used,至少如果客户端表现良好,但这并不能真正帮助您,因为您仍然无法使用该信息来控制发出哪些客户端命令。

最简单的方法可能是使用迁移命令编写核心脚本,然后为特定客户端编写包装脚本;所以如果你有core_migration.sql,你可以有另一个名为sqlplus_migration.sql的脚本刚刚做了:

SET SQLBLANKLINES ON
-- any other SQL*Plus-specific set-up you want
SET PAGESIZE 0
SET LINESIZE 200
SET SERVEROUTPUT ON SIZE UNLIMITED
WHENEVER SQLERROR EXIT FAILURE
-- etc.
-- Run core migration script
@core_migration
exit 0;

SQL*Plus 需要能够找到核心脚本,因此最好/有必要使用 substitution variable 传递完整路径:

...
SET DEFINE ON
-- Run core migration script passed via command line
@&&1
exit 0;

...然后将其称为:

sqlplus -s -l usr/pwd @sqlplus_migration /path/to/core_migration.sql

(我不喜欢将凭据放在命令行上;您的脚本可以提示输入它们,但您建议您希望它是非交互式的)。

我不熟悉 Flyway - 它可能只是想调用核心脚本而不需要额外的步骤。

【讨论】:

您提供的客户链接很酷。我可以从 PL/SQL 执行 sql 文件吗? @ka2m - 不,您不能执行文件,PL/SQL 块在服务器上执行,无法看到客户端的文件或运行 SQL*Plus 命令(如 @ 或 start )。您可以使用 utl_file 读取文件,提取语句,运行它们 - 但前提是文件在服务器上,即使这样也不简单......

以上是关于在 PL/SQL 中使用 oracle SET 值的主要内容,如果未能解决你的问题,请参考以下文章

使用带有布尔输入参数的 PL/SQL 在 oracle 中调用 java 存储过程

在 oracle 中使用正则表达式查找 POBOX - PL/SQL

我可以在 oracle pl/sql developer 中使用此代码吗

如何在 Oracle 中调试 PL/SQL 集合的值?

ORACLE PL/SQL 中的表值函数

ORACLE PL SQL 从 SOAP XML 中提取值