Oracle实现数据不存在则插入,数据存在则更新(insert or update)

      思路是写一个函数,先按条件查询数据,假设查询到数据则更新。假设没有查询到数据则插入:

create or replace function fn_merge_index(statdate      in date,
                                          cpid          in varchar2,
                                          indextypecode in number,
                                          indexitemcode in number,
                                          indexdata     in varchar2)
  return number is
  numb number;
begin
  select count(*)
    into numb
    from cp_index_statistics_rec
   where stat_date = to_date(to_char(statdate, 'yyyy/mm/dd'), 'yyyy/mm/dd')
     and cp_id = cpid
     and index_type_code = indextypecode
     and index_item_code = indexitemcode;
  if numb = 0 then
    --数据不存在,insert
    begin
      insert into cp_index_statistics_rec
        (stat_id,
         stat_date,
         diagnosis,
         cp_id,
         is_validate,
         index_type_code,
         index_item_code,
         stat_data,
         stat_create_date,
         cp_name)
      values
        (cp_index_statistics_rec_seq.nextval,
         to_date(to_char(statdate, 'yyyy/mm/dd'), 'yyyy/mm/dd'),
         '',
         cpid,
         1,
         indextypecode,
         indexitemcode,
         indexdata,
         (select sysdate from dual),
         (select cp_name from cp_templet_master where cp_id = cpid));
      commit;
    end;
  else
    --数据存在,update
    begin
      update cp_index_statistics_rec
         set is_validate      = 1,
             stat_data        = indexdata,
             stat_create_date =
             (select sysdate from dual)
       where stat_date = to_date(to_char(statdate, 'yyyy/mm/dd'), 'yyyy/mm/dd')
         and cp_id = cpid
         and index_type_code = indextypecode
         and index_item_code = indexitemcode;
      commit;
    end;
  end if;
  return numb;
end fn_merge_index;
注意to_date(to_char(statdate, 'yyyy/mm/dd'), 'yyyy/mm/dd')这个写法,假设写成to_date(statdate, 'yyyy/mm/dd'),依据NLS不同。可能导致数据出错。详细请看这里


另外oracle提供了merge into能够实现此功能。理论上讲比上面的效率会高。可是没做试验。merge into有个缺点就是在10g下面版本号的oracle中会出现故障,导致比較严重的后果(据说会把全部的数据都更新,而9i又不支持在update后加条件),所以我没有採用这种方法。

merge into的使用方法:

merge into bonuses d 
using (select employee_id, salary, department_id from employees 
where department_id = 80) s 
on (d.employee_id = s.employee_id) 
when matched then update set d.bonus = d.bonus + s.salary*.01 
when not matched then insert (d.employee_id, d.bonus) 
values (s.employee_id, s.salary*0.01); 

另外还有个思路。直接update,运行后会返回受影响的行数。假设行数为0,表示没有符合条件的数据。后面运行insert;假设行数大于0。表示有符合条件的行数且update运行成功。

posted on 2016-01-19 14:11  gcczhongduan  阅读(1325)  评论(0编辑  收藏  举报