思路是写一个函数,先按条件查询数据,假设查询到数据则更新。假设没有查询到数据则插入:
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运行成功。