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运行成功。

转载于:https://www.cnblogs.com/gcczhongduan/p/5142090.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 MyBatis 中,可以使用 `<insert>` 标签来处理插入操作,使用 `<update>` 标签来处理更新操作。但是,如果你想实现一个插入更新操作,你需要写两个不同的 SQL 语句,这很麻烦。幸运的是,Oracle 提供了一个 MERGE 语句,可以同时实现插入更新操作。 下面是一个基本的 Oracle MERGE 语句示例: ```sql MERGE INTO table_name t USING (SELECT ? col1, ? col2, ? col3 FROM dual) s ON (t.key_column = ?) WHEN MATCHED THEN UPDATE SET t.col1 = s.col1, t.col2 = s.col2, t.col3 = s.col3 WHEN NOT MATCHED THEN INSERT (t.key_column, t.col1, t.col2, t.col3) VALUES (?, ?, ?, ?) ``` 其中,`table_name` 是要插入更新的表名;`key_column` 是用于匹配的列名;`col1`、`col2`、`col3` 是要插入更新的列名;`?` 是占位符,用于传递参数。 在 MyBatis 中,你可以使用 `<update>` 和 `<insert>` 标签来执行这个 MERGE 语句。下面是一个示例: ```xml <update id="insertOrUpdate" parameterType="com.example.entity.MyEntity"> MERGE INTO my_table t USING (SELECT #{col1} col1, #{col2} col2, #{col3} col3 FROM dual) s ON (t.id = #{id}) WHEN MATCHED THEN UPDATE SET t.col1 = s.col1, t.col2 = s.col2, t.col3 = s.col3 WHEN NOT MATCHED THEN INSERT (t.id, t.col1, t.col2, t.col3) VALUES (#{id}, #{col1}, #{col2}, #{col3}) </update> ``` 在这个示例中,`MyEntity` 是一个 Java 实体类,包含 `id`、`col1`、`col2`、`col3` 四个属性。`parameterType` 属性指定了传递给 SQL 语句的参数类型。在 SQL 语句中,使用 `#{}` 占位符来引用 Java 实体类中的属性。 当你调用这个 SQL 语句时,如果 `id` 已经存在于表中,则会更新 `col1`、`col2`、`col3` 列的值;否则,会插入新的一行,其中包括 `id`、`col1`、`col2`、`col3` 列的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值