在带有 pl/sql 的参考游标中使用日期

Using date in ref cusor with pl/sql

我有一个变量:acc_date,日期类型。

它从游标中获取它的值,当我将它的值插入到记录器时 table 作为:

insert into logger values(1,acc_date);

当 select 来自记录器的输出是

1   01-JAN-10

但是当我用它来比较另一个游标中的另一个日期值时

OPEN c_get_date_id 
 for 'SELECT Date_D.DATEKEY from Date_D where Date_D.DATEVALUE='||acc_date;
     EXIT WHEN c_get_date_id%NOTFOUND;
     FETCH c_get_date_id
        INTO date_id;
      insert into logger values (1,'Now with date_id'||date_id);
CLOSE c_get_date_id;

发生错误:

Error report:
ORA-00904: "JAN": invalid identifier
ORA-06512: at "HW.FILLFACT", line 82
ORA-06512: at line 1
00904. 00000 -  "%s: invalid identifier"
*Cause:    
*Action:

强文本

您至少需要在日期周围添加一些引号:

....'  where Date_D.DATEVALUE='''||acc_date||'''';

字符串中的双撇号将连接成一个撇号,因此表达式变为

 where Date_D.DATEVALUE='....';

为了让事情更简单,我还要添加一个特定的 to_date:

.... ' where Date_D.DATEVALUE=to_date(''' || acc_date || ', ''dd-mon-yy'')';

目前您的动态查询被解释为:

SELECT Date_D.DATEKEY from Date_D where Date_D.DATEVALUE=01-JAN-10

错误是因为没有引用日期的字符串表示形式,所以它将 JAN 视为标识符 - 没有任何内容与该名称匹配。您可以将日期值括在引号中:

open c_get_date_id
  for 'SELECT Date_D.DATEKEY from Date_D where Date_D.DATEVALUE='''||acc_date||'''';

但是您将日期视为字符串,并使用会话的 NLS_DATE_FORMAT 强制将所有 table 值转换为要比较的字符串。最好将其作为日期进行比较(尽管这在某种程度上假设您的所有值都将时间部分设置为午夜):

open c_get_date_id 
  for select date_d.datekey from date_d where date_d.datevalue = acc_date;

虽然你的出口在错误的地方,而且你没有循环,所以也许你想要:

open c_get_date_id 
  for select date_d.datekey from date_d where date_d.datevalue = acc_date;
loop
  fetch c_get_date_id into date_id;
  exit when c_get_date_id%notfound;
  insert into logger values (1, 'Now with date_id'||date_id);
end loop;
close c_get_date_id;

如果你一开始只有一个值,你可能根本不需要循环或游标,而是可以做一个简单的 select ... into

select date_d.datekey into date_id from date_d
where date_d.datevalue = acc_date;
insert into logger values (1, 'Now with date_id'||date_id);

当然,如果您的 table 中没有匹配日期或多个匹配日期,那当然会出错,并且您需要处理它 - 但我猜您还是想要.