SQLPlus: ORA-01756: 带引号的字符串未正确终止

SQLPlus: ORA-01756: quoted string not properly terminated

我正在尝试使用 Oracle 中的 SQLPlus 更新 table。我的更新语句如下,但是我在这方面遇到了错误:

UPDATE mytable
   SET mycol =
          '
CREATE OR REPLACE function stg.myfun(i_run_id number, i_rec number default 0) return number as 
begin
 insert into stg.tab (col1,col2,col3,col4,col5,col6,col7)
  select src.col1, src.col2, i_run_id, src.col4,''myval'', src.s1, src.s2 
    from stg.sourcetab src
   order by col1;
 return SQL%ROWCOUNT;
exception WHEN OTHERS THEN
 IF SQLCODE = -1  
  THEN
   if i_rec>15 
   then raise;
   else return stg.myfun(i_run_id, i_rec+1);
   end if;
  ELSE
   raise; 
 end if;
end;
'
where 1 = 1
and gn = 'value';
commit;

错误是:

ERROR:
ORA-01756: quoted string not properly terminated

SP2-0734: unknown command beginning "return SQL..." - rest of line ignored.
SP2-0734: unknown command beginning "exception ..." - rest of line ignored.
SP2-0734: unknown command beginning "IF SQLCODE..." - rest of line ignored.
SP2-0042: unknown command "THEN" - rest of line ignored.
SP2-0044: For a list of known commands enter HELP and to leave enter EXIT.
SP2-0734: unknown command beginning "if i_rec>1..." - rest of line ignored.
SP2-0042: unknown command "then raise" - rest of line ignored.
SP2-0734: unknown command beginning "else retur..." - rest of line ignored.
SP2-0042: unknown command "end if" - rest of line ignored.
SP2-0044: For a list of known commands enter HELP and to leave enter EXIT.
SP2-0042: unknown command "ELSE" - rest of line ignored.
SP2-0042: unknown command "raise" - rest of line ignored.
SP2-0042: unknown command "end if" - rest of line ignored.
SP2-0042: unknown command "end" - rest of line ignored.
SP2-0044: For a list of known commands enter HELP and to leave enter EXIT.
SP2-0042: unknown command "'" - rest of line ignored.
SP2-0734: unknown command beginning "where 1 = ..." - rest of line ignored.
SP2-0734: unknown command beginning "and gn..." - rest of line ignored.

一种方法是将您的语句包装在一个简单的 PL/SQL 块中:

SQL> begin
  2  UPDATE mytable
  3     SET mycol =
  4            '
  5  CREATE OR REPLACE function stg.myfun(i_run_id number, i_rec number default 0) return number as
  6  begin
  7   insert into stg.tab (col1,col2,col3,col4,col5,col6,col7)
  8    select src.col1, src.col2, i_run_id, src.col4,''myval'', src.s1, src.s2
  9      from stg.sourcetab src
 10     order by col1;
 11   return SQL%ROWCOUNT;
 12  exception WHEN OTHERS THEN
 13   IF SQLCODE = -1
 14    THEN
 15     if i_rec>15
 16     then raise;
 17     else return stg.myfun(i_run_id, i_rec+1);
 18     end if;
 19    ELSE
 20     raise;
 21   end if;
 22  end;
 23  '
 24  where 1 = 1
 25  and gn = 'value';
 26  end;
 27  /

PL/SQL procedure successfully completed.
drop table junk;

create table junk( id number(1) not null
        , stmt varchar2(200) )
/

insert into junk values ( 1, null );
commit;

update junk
set stmt = q'[ select ename from emp where ename = 'KING'; ]'
where id = 1
;

commit
;

select * from junk
;

结果

        ID STMT
---------- --------------------------------------------------
         1  select ename from emp where ename = 'KING';

由于您专门询问 SQL*Plus,您 可以SQL terminator character 更改为字符串中未出现的内容,或者完全禁用它,其中任何一个都会停止将字符串中行末尾的分号解释为语句分隔符:

set sqlterminator off

UPDATE mytable
   SET mycol =
          '
CREATE OR REPLACE function stg.myfun(i_run_id number, i_rec number default 0) return number as 
begin
 insert into stg.tab (col1,col2,col3,col4,col5,col6,col7)
  select src.col1, src.col2, i_run_id, src.col4,''myval'', src.s1, src.s2 
    from stg.sourcetab src
   order by col1;
 return SQL%ROWCOUNT;
exception WHEN OTHERS THEN
 IF SQLCODE = -1  
  THEN
   if i_rec>15 
   then raise;
   else return stg.myfun(i_run_id, i_rec+1);
   end if;
  ELSE
   raise; 
 end if;
end;
'
where 1 = 1
and gn = 'value'
/

1 row updated.

set sqlterminator on

commit;

Commit complete.

请注意更新语句本身现在必须在新行中以斜线结束(或者以您指定的字符结束,如果您不完全关闭它的话)。我已经 re-enabled 它允许分号再次用于提交。

然而,这在 SQL Developer 中不起作用(至少在 4.2 中,它说 set sqlterminator 已过时)或可能其他同样困惑的客户端。包装在 PL/SQL 块中可能是更好的通用解决方案;或者使用绑定变量,但是你也必须小心地分配它们的值。

您还可以使用 the alternative quoting mechanism 来避免需要转义字符串中的单引号(即 ''myval''),但这不会停止 SQL*加上处理尾随分号作为语句分隔符,因此如果您使用任何其他方法,这将是一种改进。