在带有 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 中没有匹配日期或多个匹配日期,那当然会出错,并且您需要处理它 - 但我猜您还是想要.
我有一个变量: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 中没有匹配日期或多个匹配日期,那当然会出错,并且您需要处理它 - 但我猜您还是想要.