总结下。使用merge比传统的先判断再选择插入或更新快很多。
1)主要功能

提供有条件地更新和插入数据到数据库表中

如果该行存在,执行一个UPDATE操作,如果是一个新行,执行INSERT操作

    — 避免了分开更新

    — 提高性能并易于使用

    — 在数据仓库应用中十分有用

2)MERGE语句的语法如下:

MERGE [hint] INTO [schema .] table [t_alias] USING [schema .]

{ table | view | subquery } [t_alias] ON ( condition )

WHEN MATCHED THEN merge_update_clause

WHEN NOT MATCHED THEN merge_insert_clause;

备注:当使用NOT MATCHED的时候,on里面关联的必须是主键,否则插入报错

还是看例子就知道怎么回事:

MERGE INTO copy_emp c   

USING employees e   

ON (c.employee_id=e.employee_id)   

WHEN MATCHED THEN  

UPDATE SET  

c.first_name=e.first_name,   

c.last_name=e.last_name,   

c.department_id=e.department_id   

WHEN NOT MATCHED THEN  

INSERT VALUES(e.employee_id,e.first_name,e.last_name,   

e.email,e.phone_number,e.hire_date,e.job_id,   

e.salary,e.commission_pct,e.manager_id,   

e.departmetn_id); 

MERGE INTO copy_emp c

USING employees e

ON (c.employee_id=e.employee_id)

WHEN MATCHED THEN

UPDATE SET

c.first_name=e.first_name,

c.last_name=e.last_name,

c.department_id=e.department_id

WHEN NOT MATCHED THEN

INSERT VALUES(e.employee_id,e.first_name,e.last_name,

e.email,e.phone_number,e.hire_date,e.job_id,

e.salary,e.commission_pct,e.manager_id,

e.departmetn_id);

3)使用merge的注意事项:

创建测试表:

CREATE TABLE MM (ID NUMBER, NAME VARCHAR2(20));

CREATE TABLE MN (ID NUMBER, NAME VARCHAR2(20));

插入数据

INSERT INTO MM VALUES (1, 'A');

INSERT INTO MN VALUES (1, 'B');

执行:

MERGE INTO MN A

    USING MM B

    ON(A.ID=B.ID)

    WHEN MATCHED THEN

    UPDATE SET A.ID = B.ID

    WHEN NOT MATCHED THEN

    INSERT VALUES(B.ID, B.NAME);

ON(A.ID=B.ID)

报错,原因是on子句的使用的字段不能够用于update,即Oracle不允许更新用于连接的列

修改:

MERGE INTO MN A

    USING MM B

    ON(A.ID=B.ID)

    WHEN MATCHED THEN

    UPDATE SET A.NAME = B.NAME

    WHEN NOT MATCHED THEN

    INSERT VALUES(B.ID, B.NAME);

ON(A.ID=B.ID)

再插入:INSERT INTO MM VALUES (1, 'C');

再执行:

MERGE INTO MN A

    USING MM B

    ON(A.ID=B.ID)

    WHEN MATCHED THEN

    UPDATE SET A.NAME = B.NAME

    WHEN NOT MATCHED THEN

    INSERT VALUES(B.ID, B.NAME);

ON(A.ID=B.ID)

报错,原因无法在源表中获得一组稳定的行

4)更新同一张表的数据。需要注意下细节,因为可能涉及到using的数据集为null,所以要使用count()函数。

MERGE INTO mn a

   USING (select count(*) co from mn where mn.ID=4) b

   ON (b.co<>0)--这里使用了count和<>,注意下,想下为什么!

   WHEN MATCHED THEN

      UPDATE

         SET a.NAME = 'E'

         where a.ID=4

   WHEN NOT MATCHED THEN

      INSERT

      VALUES (4, 'E');

---------

对于Oracle的两表联合更新的场景(有A、B两表,以A.id=B.id关联,根据B表中的记录更新A表中的相应字段),一般有update内联视图和merge两种方式,下面举例介绍:

创建用例表:

CREATE TABLE test1(ID NUMBER(10),NAME VARCHAR2(20));

INSERT INTO test1 VALUES(1,'lucy');

INSERT INTO test1 VALUES(2,'lily');

CREATE TABLE test2(ID NUMBER(10),NAME VARCHAR2(20));

INSERT INTO test2 VALUES(1,'lucy');

INSERT INTO test2 VALUES(2,'hanmeimei');

merge方式:

MERGE INTO test1 USING test2

ON (test1.id = test2.id)

WHEN MATCHED THEN UPDATE

SET test1.name = NVL2(test1.name,test2.name,test1.name);

merge方法是最简洁,效率最高的方式,在大数据量更新时优先使用这种方式。

update内联视图方式:

使用这种方式必须在test2.id上有主键(这里很好理解,必须保证每一个test1.id对应在test2里只有一条记录,如果test2中有多条对应的记录,怎么更新test1?),一般而言这种方式代价比merge方式稍高。

ALTER TABLE test2 ADD CONSTRAINT pk_test2 PRIMARY KEY(ID);

UPDATE (SELECT a.id aid,a.name aname,b.id bid,b.name bname FROM TEST1 a,test2 b WHERE a.id=b.id) t

SET aname = NVL2(aname,bname,aname);

使用并行,加快大量数据更新:

MERGE /*+parallel(test1,4)*/ INTO test1 USING test2

ON (test1.id = test2.id)

WHEN MATCHED THEN UPDATE

SET test1.name = NVL2(test1.name,test2.name,test1.name);

oracle使用 merge 更新或插入数据的更多相关文章

  1. 在oracle中使用merge into实现更新和插入数据

    目录 oracle中使用merge into DUAL表解释 使用场景 用法 单表 多表 oracle中使用merge into DUAL表解释 在Oracle数据库中,dual是Oracle中的一个 ...

  2. oracle数据库表中,插入数据的时候如何产生一个 字母+数字 编号?

    Oracle 语句中“||”代表什么啊? oracle数据库表中,插入数据的时候如何产生一个 字母+数字 编号? 排序的话,用order by来处理即可.比如:cola123a234b999b335s ...

  3. mybatis oracle两种方式批量插入数据

    mybatis oracle两种方式批量插入数据 注意insert,一定要添加: useGeneratedKeys="false" ,否者会报错. <insert id=&q ...

  4. oracle利用merge更新一表的某列数据到另一表中

    假设你有两张表 t1 表 -------------------------- id |    name   |   pwd 1  |      n1     | t2 表 ------------- ...

  5. ADO.net 更新和插入数据 遇到null 执行不成功

    首先交代下背景,遇到一个问题:SqlCommand新增记录时,参数为null时,运行并不报错,只是返回(0),也就是更新失败. 在用C#往数据库里面插入记录的时候, 可能有的字段我们并不赋值(有可能是 ...

  6. oracle存储过程含参数的插入数据

    create or replace procedure proczipcodebyzipinsert(   i_zipcode  in  zipcode.zip%type,   i_city in z ...

  7. Excel 提供数据 更新或者插入数据 通过函数 自动生成SQL语句

    excel 更新数据 ="UPDATE dbo.yt_vehicleExtensionBase SET yt_purchase_date='"&B2&"' ...

  8. python mysql 更新和插入数据无效

    注意,在删除和增加后必须执行conn.commit()才有效,否则操作无效.

  9. [转]Oracle存在则更新,不存在则插入

    原文:http://hi.baidu.com/mawf2008/item/eec8c7ad1c5be5ae29ce9da6 merge into a using bon (a.a=b.b)when m ...

随机推荐

  1. python的XML处理模块ElementTree

    ElementTree是python的XML处理模块,它提供了一个轻量级的对象模型.它在Python2.5以后成为Python标准库的一部分,但是Python2.4之前需要单独安装.在使用Elemen ...

  2. __del__,item系列 ,hash方法,__eq__,

    # 构造方法 申请一个空间# 析构方法 释放一个空间 # 某个对象借用了操作系统的资源,还要通过析构方法归还回去:文件资源 网络资源 # 垃圾回收机制 class A: def __del__(sel ...

  3. Executor框架(七)Future 接口、FutureTask类

    Future接口介绍   Future 表示异步计算的结果.它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果.   Future 一般由 ExecutorService 的submi ...

  4. 显式锁(三)读写锁ReadWriteLock

    前言:   上一篇文章,已经很详细地介绍了 显式锁Lock 以及 其常用的实现方式- - ReetrantLock(重入锁),本文将介绍另一种显式锁 - - 读写锁ReadWriteLock.    ...

  5. Spring boot @PropertySource, @ImportResource, @Bean

    @PropertySource:加载指定的配置文件 /** * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉SpringBoot将本类 ...

  6. Objective C, erum 枚举类型

    typedef NS_ENUM(NSInteger, MYENUM) { TYPE1, TYPE2, TYPE3 };

  7. iperf点对点网络性能测试工具

    什么是Iperf?Iperf 是一个网络性能测试工具.Iperf可以测试TCP和UDP带宽质量.Iperf可以测量最大TCP带宽,具有多种参数和UDP特性.Iperf可以报告带宽,延迟抖动和数据包丢失 ...

  8. Spring MVC 接受的请求参数

    目录 1. 概述 2. 详解 2.1 处理查询参数 2.2 处理路径参数接受输入 2.3 处理表单 3. 补充内容 3.1 Ajax/JSON 输入 3.2 multipart参数 3.3 接收 he ...

  9. C++ 0x 使用 shared_ptr 自动释放, 防止内存泄漏

    最近在研究 cocos2d-x 3.0 ,它在创建类的对象时比如 Layer 时, 并不是直接使用 new , 而是使用一个宏方法  CREATE_FUNC(MyLayer);. 这个宏就是自动的创建 ...

  10. ArcGIS案例学习笔记2_2

    ArcGIS案例学习笔记2_2 联系方式:谢老师,135_4855_4328,xiexiaokui#qq.com 时间:第二天下午 2018年8月12日 案例1:模型构建器,山顶点提取 背景:数据量大 ...