merge更新或插入同一张表

一段业务逻辑,需要先判断一条记录在数据库中是否有存在,若存在则更新该记录,若不存在则插入记录。

应用之前的做法是:

1、先用条件判断记录在数据库中的个数。

2.1、若count(*)>0,则执行UPDATE操作。

2.2、若count(*)=0,则执行INSERT操作。

1、先插入记录。

2.1、若报ORA-001主键错误,则存在记录,此时执行UPDATE操作。

2.2、若无报错,认为插入完成。

以上两种方法,我认为都可以实现这种业务逻辑,区别在于第二种方法可能只需要一次SQL操作,前提是大部分记录都不存在,如果大部分操作都是UPDATE操作,可以这么改:

1、先更新。

2.1、若更新条数>0,则存在记录,执行完成。

2.2、若更新条数=0,则不存在记录,执行INSERT操作。

以上逻辑最差的情况就是需要执行两次SQL,如果数据量不大,则可以忽略消耗时间,但如果是大表,可能消耗就会翻倍。针对这种情况,或许可以考虑使用merge。一般使用merge都是用来将一个表数据导入另一个表,但他可以对同一个表操作,例如:

需求:RULE_COLLISION表:根据app_name、rule_id和start_time更新collision_count字段,或直接插入一条新的记录。

SQL:

merge into RULE_COLLISION t1

using (SELECT ‘TEST‘ app_name, ‘TIMELIMIT_COMPONENT‘ MODULE, ‘规则一‘ RULE_ID, 3 COLLISION_COUNT, to_date(‘2014-07-21‘, ‘yyyy-mm-dd‘) start_time from dual) t2

on (t1.app_name = t2.app_name AND t1.rule_id = t2.rule_id AND t1.start_time = t2.start_time)

when matched then

update SET t1.collision_count = t2.collision_count

when not matched then

insert values (t2.app_name, t2.MODULE, t2.RULE_ID, t2.COLLISION_COUNT, t2.start_time);

通过伪表dual,实现RULE_COLLISION表的自我更新或插入,这种做法和上面逻辑都是相同的,但这样只会执行一次SQL,如下是执行计划:

Execution Plan

----------------------------------------------------------

Plan hash value: 3989089639

-----------------------------------------------------------------------------------------------------------

| Id  | Operation                      | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------------------------------------

|   0 | MERGE STATEMENT                |                          |     1 |   322 |     2   (0)| 00:00:01 |

|   1 |  MERGE                         | RI_RULE_COLLISION_DETAIL |       |       |            |          |

|   2 |   VIEW                         |                          |       |       |            |          |

|   3 |    NESTED LOOPS OUTER          |                          |     1 |   224 |     2   (0)| 00:00:01 |

|   4 |     FAST DUAL                  |                          |     1 |       |     2   (0)| 00:00:01 |

|   5 |     TABLE ACCESS BY INDEX ROWID| RI_RULE_COLLISION_DETAIL |     1 |   224 |     0   (0)| 00:00:01 |

|*  6 |      INDEX UNIQUE SCAN         | RULE_COLLISION_ID        |     1 |       |     0   (0)| 00:00:01 |

-----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

6 - access("T1"."APP_NAME"(+)=‘GALT‘ AND "T1"."RULE_ID"(+)=‘规则一‘ AND "T1"."START_TIME"(+)=TO_DATE(‘ 2014-07-21 00:00:00‘, ‘syyyy-mm-dd hh24:mi:ss‘))

Note

-----

- dynamic sampling used for this statement (level=2)

Statistics

----------------------------------------------------------

0  recursive calls

3  db block gets

2  consistent gets

0  physical reads

0  redo size

829  bytes sent via SQL*Net to client

1315  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

1  sorts (memory)

0  sorts (disk)

1  rows processed

这里用到的是NESTED LOOPS OUTER,不是HASH JOIN,如果是两表操作是否就不同了?这块后面还需要实验研究下,有高手可以请教请教!

merge更新或插入同一张表

时间: 2024-07-31 10:41:28

merge更新或插入同一张表的相关文章

多表联合查询后去重复数据后重新插入第一张表解决办法

select goods_id,goods_type,goods_name,in_buy_price,ROUND(sum(in_total_price)/sum(in_amount),2),count(*) from in_warehouse_detail group by goods_id,goods_type,goods_name order by goods_id,goods_type,goods_name 查询结果如下: 另一张关联表[通过goods表的goods_Id和in_wareh

Oracle中用随机数更新字段----将一张表的数据插入另一张表----环境设置

DECLARE CURSOR recordCursor IS SELECT longitude,latitude FROM WR_WIUST_B_SEC FOR UPDATE; recordRow recordCursor % ROWTYPE; BEGIN OPEN recordCursor; LOOP FETCH recordCursor INTO recordRow; IF recordCursor % NOTFOUND THEN EXIT; ELSE UPDATE WR_WIUST_B_S

sql中如何 将一张表的数据 更新到另外一张表的字段中

今天操作数据库       有个需求需要从一张流水表中有用户付款金额    还有一张  是用户的结算金额    每个用户的付款和结算费率和手续费等都不一样   需要将剩余可以结算的金额查询出来  进行更新到各自对应的用户后面  花了几分钟写出来去测试了一下  没问题 万变不离其中   依然还是  在 update  +表(及其关联表) +set  +更改字段 +where 条件 update merchant m join ( select pc.cp_channel channelId,0.0

Oracle两表关联(join)更新字段值一张表到另一张表

[采用视图更新的方式] 有需求A表,B表,需要将B表中的name字段更新到A表中的name,两表有id关联,代码如下: update  (select a.name aname, b.name bname from A a, B b where a.id = b.id) set aname = bname; --注:两表关联属性id必须为unique index或primary key

SQL 将2张不相关的表拼接成2列,批量更新至另一张表

update SO_Master set LotteryNo=t2.LotteryNo,UpdateTime=GETDATE() --select sm.LotteryNo,sm.SysNo,t2.LotteryNo from SO_Master sm inner join ( select SysNo,ROW_NUMBER() over(order by sysno asc) rIndex from SO_Master where WebSiteSysNo =6 and SOAmt >=800

批量插入一张表的数据,并且生成不同的uuid

INSERT INTO party_branchSELECT UUID(),m.name,m.secreta_name,m.contacts_name,m.contact_phon,m.category_name,m.type,'admin','admin', NOW(),NOW() FROM mypary_branch m UPDATE party_branch SET id =REPLACE(id,'-','') 必须分开执行 如果 INSERT INTO party_branchSELEC

Mysql查询结果作为另一张表的更新内容

1.将查询结果中有用的数据用分隔符获取,更新到另一张表. DELIMITER $$ DROP FUNCTION IF EXISTS `func_splitString` $$ CREATE FUNCTION `func_splitString` ( f_string VARCHAR(1000),f_delimiter VARCHAR(5),f_order INT) RETURNS VARCHAR(255) CHARSET utf8 BEGIN DECLARE result VARCHAR(255

使用Merge存储引擎实现MySQL分表

一.使用场景 Merge表有点类似于视图.使用Merge存储引擎实现MySQL分表,这种方法比较适合那些没有事先考虑分表,随着数据的增多,已经出现了数据查询慢的情况. 这个时候如果要把已有的大数据量表分开比较痛苦,最痛苦的事就是改代码.所以使用Merge存储引擎实现MySQL分表可以避免改代码. Merge引擎下每一张表只有一个MRG文件.MRG里面存放着分表的关系,以及插入数据的方式.它就像是一个外壳,或者是连接池,数据存放在分表里面. 对于增删改查,直接操作总表即可. 二.建表 1.用户1表

Oracle两张表关联批量更新其中一张表的数据

Oracle两张表关联批量更新其中一张表的数据 方法一(推荐): UPDATE 表2 SET 表2.C = (SELECT B FROM 表1 WHERE 表1.A = 表2.A) WHERE EXISTS (SELECT 1 FROM 表1 WHERE 表1.A = 表2.A); 尤其注意最后的外层where条件尤为重要,是锁定其批量更新数据的范围. 方法二: MERGE INTO 表2 USING 表1 ON (表2.A = 表1.A) -- 条件是 A 相同 WHEN MATCHED TH