如何在表中插入变量-1

时间:2012-11-15 08:39:02

标签: oracle variables insert to-date to-char

我在尝试通过从另一个表中选择以日期作为条件来插入表时遇到问题。日期将从另一个表而不是从Oracle检索,因为应用程序存储其自己的系统日期(即今天可能是未来10年 - 20201124)。然后,日期的条件是ASOF = TODAY-1和DATE在TODAY和TODAY +1之间。

这是我尝试做的事情:

declare
   v_TODAY number;
begin 
   select TODAY into v_TODAY from LOCATION;
   execute immediate 'truncate table table_EOD';
   execute immediate 'insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
      from table
      where ASOF = to_char(to_date(v_TODAY)-1) 
      and DATE between v_TODAY and to_char(to_date(v_TODAY)+1)';
end;
/

我收到的错误是:

Error report:
ORA-00904: "V_TODAY": invalid identifier
ORA-06512: at line 6
00904. 00000 -  "%s: invalid identifier"
你能告诉我什么是错的吗?感谢。

2 个答案:

答案 0 :(得分:1)

您收到的错误是正确的v_today不是EXECUTE IMMEDIATE语句范围内的有效标识符。您应该使用bind variable代替:

declare
   v_TODAY number;
begin 
   select TODAY into v_TODAY from LOCATION;
   execute immediate 'truncate table table_EOD';
   execute immediate 'insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
      from table
      where ASOF = to_char(to_date(:1)-1) 
      and DATE between :1 and to_char(to_date(:1)+1)'
     using v_today, v_today, v_today;
end;
/

还有两点。首先,如果您在LOCATION中有多行,那么您的select into ...将无效。这是因为v_today只能包含一个值。将引发TOO_MANY_ROWS异常;你会选择太多行!

其次,没有必要进行第二次EXECUTE IMMEDIATE。如果在编译块之前不存在您引用的对象,或者您正在动态生成SQL,则只需在执行立即执行DML。

您仍然必须执行truncate inside和EXECUTE IMMEDIATE语句,因为这是DDL。这将为您提供以下内容:

declare
   v_TODAY number;
begin 

   select TODAY into v_TODAY from LOCATION; -- Still wrong!
   execute immediate 'truncate table table_EOD';

   insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
     from table
    where ASOF = to_char(to_date(v_TODAY)-1) 
      and DATE between v_TODAY and to_char(to_date(v_TODAY)+1);
end;
/

好的,从您的评论中我刚刚意识到您实际上想要今天而不是一些随机日期,并且您使用数字作为日期在LOCATION中,这是导致错误的原因。为什么不在今天的日期使用Oracle的[sysdate]?

declare
   v_TODAY date := sysdate;
begin 

   execute immediate 'truncate table table_EOD';

   insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
     from table
    where ASOF = trunc(sysdate) - 1
      and DATE between trunc(v_TODAY) and trunc(v_TODAY) + 1;
end;
/

如果你想使用你自己的日期,你必须找到一种方法,在LOCATION中设置一个日期而不是一个数字。

答案 1 :(得分:0)

这里不需要PL / SQL或动态SQL。

这样的事情应该这样做:

truncate table table_eod;

insert into table table_eod (key1, key2, asof, idate)
with today_data as (
   select today as v_today
   from location
)
select t.key1, t.key2, t.ASOF, t.IDATE 
from table t
  join today_data td on t.ASOF = to_char(to_date(td.v_TODAY)-1) 
      and DATE between td.v_TODAY and to_char(to_date(td.v_TODAY)+1);

如果表LOCATION包含多行,我不确定这是否会正常工作。