PL / SQL - 使用Exception插入数据

时间:2015-01-30 15:38:34

标签: plsql

我有以下代码未正确执行。我有数据存储在date_tmp(varchar)中,包括日期和非日期。我想将该列中的日期移动到date_run(日期),而不是日期的数据将移动到comments(varchar)列。当我运行以下代码时,整个数据集将移动到注释。当我编辑insert语句并运行dbms_outputline行时,它运行正常。我可能做错了什么?

DECLARE

  CURSOR getrow IS
  SELECT a.id, a.date_tmp
  FROM mycolumn a 
  WHERE a.id < 1300;

  v_date date;  

BEGIN
  FOR i in getrow LOOP
    BEGIN
      v_date := to_date(i.date_tmp, 'mm/dd/yy');  
      INSERT INTO mycolumn a(a.date_run)
      VALUES(i.date_tmp);

    EXCEPTION
      WHEN OTHERS THEN       
        --dbms_output.put_line(i.date_tmp);
        update mycolumn a
        SET a.comments = i.date_tmp
        where a.id = i.id;
    END;
  END LOOP; 
END;

3 个答案:

答案 0 :(得分:2)

您尝试将varchar i.date_tmp插入日期字段。而是插入v_date

...
INSERT INTO mycolumn a (a.date_run)
VALUES(v_date);
...

但实际上你的要求是一个举动。这要求实际更新。所以我认为你真正想做的是:

...
update mycolumn a
SET a.date_run = v_date
where a.id = i.id    
...

实际上,您可以使用一个函数来检查您是否有有效日期,然后您可以使用简单的更新语句来处理整个任务。

create or replace function is_a_date(i_date varchar2, i_pattern varchar2) 
return date 
is
begin
  return to_date(i_date, i_pattern);
exception
  when others return null;
end is_a_date;

使用该功能,您可以编写两个更新语句

update mycolumn 
   set date_run = to_date(date_tmp,'dd/mm/yy')
 where is_a_date(date_tmp, 'dd/mm/yy') is not null;

update mycolumn 
   set comment = date_tmp
 where is_a_date(date_tmp, 'dd/mm/yy') is null;

我设计了这个函数,你可以用各种方式使用它,因为它返回一个日期或null但是如果varchar不符合日期模式则没有例外。

答案 1 :(得分:1)

您有一个insert,看起来您需要一个update,就像您在异常处理程序中一样。所以只需将其更改为:

  v_date := to_date(i.date_tmp, 'mm/dd/yy');  
  update  mycolumn
      set date_run = v_date
  where   id = i.id;

或者您可以缩短为:

  update  mycolumn
      set date_run = to_date(i.date_tmp, 'mm/dd/yy')
  where   id = i.id;

答案 2 :(得分:1)

@hol解决方案对我来说是最好的方法。 如果您可以使用简单的SQL语句执行此操作,请始终避免循环和过程,您的代码将更快。 此外,如果你总是拥有一个数据固定格式,你可以使用PL / SQL函数is_a_date函数并使用SQL完成所有操作......但代码变得有点丑陋,如下所示:

update mycolumn 
   set date_run = to_date(date_tmp,'dd/mm/yy')
     where substr(date_tmp,1,2) between '1' and '31'
      and substr(date_tmp,4,2) between '1' and '12'
      and substr(date_tmp,7,2) between '00' and '99';

如果你的查询需要更快的速度,或者你在date_tmp中有大量的数据,因为函数is_a_date是确定的(总是返回相同的值,给定相同的X,Y值),你可以创建一个索引它:

create index mycol_idx on mycolumn(is_a_date(date_tmp));

当您使用该函数时,Oracle将使用您的索引,就像那些选择:

SELECT a.id, a.date_tmp
  FROM mycolumn a 
  WHERE a.id < 1300
and is_a_date(a.date_tmp) is not null;

SELECT a.id, a.date_tmp
  FROM mycolumn a 
  WHERE a.id < 1300
  and (is_a_date(a.date_tmp) is not null and is_a_date(a.date_tmp)>sysdate-5);