SQL脚本中的分号问题

Posted

技术标签:

【中文标题】SQL脚本中的分号问题【英文标题】:Semicolon issue in SQL script 【发布时间】:2019-06-27 17:15:57 【问题描述】:

我需要使用包含分号的存储过程更新列值,这会导致“引用的字符串未正确结束”的问题。

使用 Putty 连接到服务器并使用 SQL Plus 执行命令

尝试使用 /;但它没有工作

update dummy_table
  set
  col1 = 0, col2 = null, col3 = to_clob(
    'declare
    source_table varchar2(40) := :par1;
    target_table_name varchar2(40) := :par2;
    '||'
    begin  '||'
    select * from temp_table;
    end;
    '||'/'
  ), col4 = null
  where col5 = 'value_1' and col6 = 'value_7';

ER:命令应该成功执行,它应该用给定的值更新 col3

AR:带引号的字符串没有正确结束

【问题讨论】:

@ADyson 我的印象是 OP 试图使用双杠运算符连接以确保在此处生成的 col3 SQL 字符串中存在换行符。我觉得使用SET SQLBLANKLINES ON 可能会更好地完成此操作,但我不是这里的专家。 这不是“逃避问题”。是的,'||' 中的第一个单引号结束了字符串文字,但是该字符串文字后面是 || 连接运算符,然后是一个单引号,该单引号开始另一个字符串文字。 OP 观察到的行为本身不是 SQL 问题,它是 sqlplus 在遇到分号时过早识别语句的结尾。 【参考方案1】:

分号告诉 SQLPlus 你想运行你输入的命令。它不会首先看到您位于带引号的字符串的中间。 要停止此操作,请将您的整个命令包含在其自己的块中,其中分号将被视为该块的一部分,并且不要尝试执行您到目前为止输入的内容。块被 BEGIN 和 END 关键字包围。通过在单独的行中输入句点来告诉 SQLPlus 完成,然后通过输入斜杠来运行该块。

所以,如果您在 SQL*Plus 中输入,它看起来像这样:

BEGIN
update dummy_table
  set
  col1 = 0, col2 = null, col3 = to_clob(
    'declare
    source_table varchar2(40) := :par1;
    target_table_name varchar2(40) := :par2;
    '||'
    begin  '||'
    select * from temp_table;
    end;
    '||'/'
  ), col4 = null
  where col5 = 'value_1' and col6 = 'value_7';
END;
.
/

【讨论】:

SQLPlus 从什么时候开始在一行中使用. @a_horse_with_no_name 打败了我。请参阅此页面上的“运行 PL/SQL 块”部分:docs.oracle.com/cd/E11882_01/server.112/e16604/…【参考方案2】:

您可以使用以下解决方案中提到的 Oracle 的替代引用机制技术:

UPDATE DUMMY_TABLE
SET
    COL1 = 0,
    COL2 = NULL,
    COL3 = TO_CLOB('declare
    source_table varchar2(40) := :par1;
    target_table_name varchar2(40) := :par2;
    '
    || '
    begin  '
    || '
    select * from temp_table;
    end;
    '
    || q'#/#'),
    COL4 = NULL
WHERE
    COL5 = 'value_1'
    AND COL6 = 'value_7';

字符串,包含任何特殊的 oracle 保留字符,如果您想将其视为字符串,则需要使用带引号的字符串:q'<Special symbol><Your string><Special symbol>'

请参考Oracle文档中的Alternative Quoting Mechanism技术。

【讨论】:

【参考方案3】:

SQLPlus 似乎不喜欢行尾的分号,无论它们是否是带引号的字符串的一部分。这有效,它与您的语句相同,但添加了换行符 (CR+LF):

update dummy_table
    set
    col1 = 0, col2 = null, col3 = to_clob(
      'declare
      source_table varchar2(40) := :par1;' || chr(10) || chr(13) ||'
      target_table_name varchar2(40) := :par2;' || chr(10) || chr(13) ||'
      '||'
      begin  '||'
      select * from temp_table;' || chr(10) || chr(13) ||'
      end;' || chr(10) || chr(13) ||'
      '||'/'
    ), col4 = null
    where col5 = 'value_1' and col6 = 'value_7';

【讨论】:

【参考方案4】:
set sqlterminator off
update dummy_table
  set
  col1 = 0, col2 = null, col3 = to_clob(
    'declare
    source_table varchar2(40) := :par1;
    target_table_name varchar2(40) := :par2;
    '||'
    begin  '||'
    select * from temp_table;
    end;
    '||'/'
  ), col4 = null
  where col5 = 'value_1' and col6 = 'value_7'
/
set sqlterminator on

【讨论】:

您应该编辑您的问题,以便解释您的工作以及它如何解决问题。 为什么这被否决了。它似乎解决了操作的问题(和我的)

以上是关于SQL脚本中的分号问题的主要内容,如果未能解决你的问题,请参考以下文章

什么时候需要在 Oracle SQL 中使用分号和斜杠?

如何执行sql脚本?

mysql导入sql脚本

使用java以及jdbc不使用第三方库执行sql文件脚本

如何让hibernate hbm2ddl生成带分号的SQL?

SQL 脚本中的 SQL 查询