PLSQL - 将选择查询结果存储在变量抛出错误中

时间:2013-05-13 05:07:07

标签: sql oracle plsql database-administration

我想将选择查询结果存储在PLSQL中的变量中。

SQL>var v_storedate VARCHAR2(19);
SQL>exec :v_storedate := 'select cdate from rprt where cdate between  cdate AND TO_CHAR(sysdate, 'YYYY/MM/DD-HH24-MI-SS-SSSSS') and ryg='R' and cnum='C002'';

作为

SQL>select cdate from rprt where cdate between  cdate AND TO_CHAR(sysdate, 'YYYY/MM/DD-HH24-MI-SS-SSSSS') and ryg='R' and cnum='C002';

返回:2013/04 / 27-10:06:26:794

但它会引发错误:

 ERROR at line 1: ORA-06550: line 1, column 121: PLS-00103: Encountered
 the symbol "YYYY" when expecting one of the following:
 * & = - + ; < / > at in is mod remainder not rem <an exponent (**)> <> or != or ~= >= <= <> and or like LIKE2_ LIKE4_ LIKEC_ between ||
 multiset member SUBMULTISET_ The symbol "*" was substituted for "YYYY"
 to continue. ORA-06550: line 1, column 148: PLS-00103: Encountered the
 symbol ") and ryg=" when expecting one of the following: . ( * @ % & =
 - + ; < / > at in is mod remainder not rem <an exponent (**)> <> or != or ~= >= <= <> and or like LIKE2_ LIKE4_ LIKEC_ between

3 个答案:

答案 0 :(得分:3)

在PL / SQL中,使用单引号的文字的更好方法是引用语法:http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/fundamentals.htm#CBJJDDCG

begin
  variable := q'#select cdate from rprt where cdate between  cdate AND TO_CHAR(sysdate, 'YYYY/MM/DD-HH24-MI-SS-SSSSS') and ryg='R' and cnum='C002'#'
  ...
end

...或匹配的分隔符...

begin
  variable := q'[select cdate from rprt where cdate between  cdate AND TO_CHAR(sysdate, 'YYYY/MM/DD-HH24-MI-SS-SSSSS') and ryg='R' and cnum='C002']'
  ...
end

您也可以在SQL * Plus中尝试...不确定它是否在那里工作。

答案 1 :(得分:1)

如果要存储查询的结果,则需要使用select ... into;此时您正在尝试存储实际查询的文本,而不是其结果。如果你想这样做,你需要像其他答案所指出的那样转义单引号字符,并增加变量大小。

var v_storedate VARCHAR2(19);
exec select cdate into :v_storedate from rprt where cdate between cdate AND TO_CHAR(sysdate, 'YYYY/MM/DD-HH24-MI-SS-SSSSS') and ryg='R' and cnum='C002';
print v_storedate

使用普通匿名块而不是SQL * Plus'execute速记更容易处理。在将其转换为字符串时,您还应该提供明确的日期格式掩码:

begin
    select to_char(cdate, 'YYYY/MM/DD-HH24:MI:SS')
    into :v_storedate
    from rprt
    where cdate between cdate AND TO_CHAR(sysdate, 'YYYY/MM/DD-HH24-MI-SS-SSSSS')
    and ryg='R' and cnum='C002';
end;
/

如果你想要小数秒,那么你需要让你的变量更大,因为19个字符只会带你到秒。

无论哪种方式,您都有可能获得多个结果(这会产生ORA-02112)或没有结果(这会产生ORA-01403)。由于您的where子句没有多大意义且表内容未知,我不知道哪个更有可能。现在在这里指出你的cdate比较总是如此,而且你在那里进行隐式日期转换会在某个时刻中断。没有足够的信息可以解决这个问题。


如果您只想要日期部分:

var v_storedate VARCHAR2(10);
begin
    select to_char(cdate, 'YYYY/MM/DD')
    into :v_storedate
    ...

如果您愿意,您仍然可以使用exec,但是一旦语句的长度超过终端线路长度,它的可读性就会降低:

var v_storedate VARCHAR2(10);
exec select to_char(cdate, 'YYYY/MM/DD') into :v_storedate from ... where ... ;

答案 2 :(得分:0)

通过加倍来逃避你的内心撇号!