使用包含空格,分号和正斜杠的SQLPlus执行脚本


15

有时候,我会获得一个脚本,该脚本可以在SQL Developer或Toad中正常运行,但是需要修改才能从SQL * Plus成功运行。这是最坏的情况示例,其中包含多个带有空行,分号和正斜杠的语句:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

由于各种原因,这些语句需要从SQL * Plus运行。用简单的...即可轻松解决空白行。

set sqlblanklines on

我知道sqlterminator可以更改和/或关闭它们,但是两者都需要修改代码,前者在不解决问题的情况下解决了问题,也没有解决嵌入式斜杠问题。

最好的答案是一种通过以某种方式更改环境(如sqlblanklines所做的那样)而无需修改即可运行这些语句的方法。如果这不可能,那么也许可以通过编程方式修改脚本。我正在尝试避免手动更改。


使用SQLPLUS的命令行执行时,很容易发生此问题。当您在SQLPLUS程序中时,命令行编辑器仍然处于活动状态。结果,与命令行编辑器相关的项目(空格被解释为命令/变量,分号被视为命令结尾)。这就是为什么在您尝试登录时,密码中只有一个'@'会导致心痛的原因(@右边的所有内容都被视为数据库的名称)。在大型部署过程中,我们发现空格存在问题,迫使我们不得不通过TOAD部署内容。SQLPLUS没用
TomV 2012年

谢谢你的想法。因此,请澄清您的回答,即我所要求的是不可能的?
Leigh Riffel 2012年

能否将字符串中的回车符转换为chr(10)的插入在一行上列出?
克里斯·萨克森

@ChrisSaxon我可以,但是这个问题是如何区分应进行编码的返回值和作为语法一部分需要单独保留的返回值。如果您有办法做到这一点,请将其发布为答案。
利·里菲尔

Answers:


8

您可以使用login.sql来完成大多数操作。login.sql在登录期间执行-令人惊讶-在登录时从您的SQLPATH或当前目录加载。对于您给出的示例,您确实选择了最坏的情况。

问题是sqlterminator。无论您在其中放置什么,正斜杠都将保留为免费的sqlterminator。紧接着,sqlplus首先扫描sqlterminator,然后在扫描到字符串终止符之前执行此操作。如果您问我一个错误。只要不是单独出现在一行上,就可以在字符串中使用正斜杠。一旦sqlplus找到指定为sqlterminator的字符,它将忽略所有其他内容并停止读取。

只要不是一个斜线就可以处理正斜杠。

login.sql包含:

prompt run login.sql
show sqlterminator
show sqlblanklines
set sqlblanklines on
set sqlterminator ';'
show sqlterminator
show sqlblanklines
prompt ready login.sql
set echo on

leigh.sql包含:

INSERT INTO t1 VALUES ('fail bc semicolon
a;a
/
'); 

INSERT INTO t1 VALUES ('fail bc solo /


aa
/
');

INSERT INTO t1 VALUES ('ok / not solo


aa
/a
');

DELETE FROM t1 WHERE a = 'c


a/
';

运行脚本:

sqlplus leigh/leigh@orcl @leigh
SQL*Plus: Release 10.2.0.4.0 - Production on Thu Aug 9 22:36:20 2012

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

run login.sql
sqlterminator ";" (hex 3b)
sqlblanklines OFF
sqlterminator ";" (hex 3b)
sqlblanklines ON
ready login.sql
SQL> INSERT INTO t1 VALUES ('fail bc semicolon
  2  a;a
  3  /
ERROR:
ORA-01756: quoted string not properly terminated


SQL> ');
SP2-0042: unknown command "')" - rest of line ignored.
SQL> 
SQL> INSERT INTO t1 VALUES ('fail bc solo /
  2  
  3  
  4  aa
  5  /
ERROR:
ORA-01756: quoted string not properly terminated


SQL> ');
SP2-0042: unknown command "')" - rest of line ignored.
SQL> 
SQL> INSERT INTO t1 VALUES ('ok / not solo
  2  
  3  
  4  aa
  5  /a
  6  ');

1 row created.

SQL> 
SQL> DELETE FROM t1 WHERE a = 'c
  2  
  3  
  4  a/
  5  ';

0 rows deleted.

无需摆弄开始/结束块。无论命令在何处,无论在字符串中与否,都无法处理sqlterminator命令,不能在字符串中仅使用正斜杠的行进行处理。


1
谢谢你的证明。我已经类似地使用了login.sql文件设置。因此,基本上,这证实了为什么我想做的事情无法完成。
雷·里菲尔

1
一个小的变化是使用运行程序脚本进行设置并调用真实脚本。将成为sqlplus leigh / leigh @ orcl @runner leigh。这比login.sql更加灵活
ik_zelf 2012年

1

如果放置在BEGIN ... END块中,则具有空行和分号的插入语句将成功。可以使用脚本来完成此更改,但是如果脚本包含无法在不立即执行的情况下无法在块内运行的DDL语句,则脚本将失败。

此解决方案也不能解决嵌入式/问题。


过去,我使用perl / DBD脚本来执行此操作以避免sqlplus。乐于分享...
Philᵀᴹ

@Phil谢谢,但是SQLPlus在99.9%的情况下都能正常工作,因此我宁愿不添加其他工具。
Leigh Riffel'4

1

我的解决方法:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

似乎在body语句中忽略了命令终止符。


请参阅我的答案,以了解为什么这对于DDL语句或嵌入式斜杠不是一个好的解决方案。
Leigh Riffel 2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.