总结下。使用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. js基础和运算符

    1.什么JavaScript?    运行环境 :    浏览器                    是一种具有安全性的客户端的脚本语言     用来实现与web页面交互 脚本语言:语言嵌入到htm ...

  2. 并发工具类(三)控制并发线程的数量 Semphore

    前言   JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...

  3. 手贱!使用django,在数据库直接删除了表

    莫名其妙的错误. 删除了migreation文件,并且更换了数据库. 1.直接makemigrations + migrate    error: no change ??  WTF 2.makemi ...

  4. Python入门-散点图绘制

    Python入门-散点图绘制  废话不说 直接上代码 import matplotlib.pyplot as plt x_values = list(range(1,1001)) y_values = ...

  5. HTML5 学习之地理定位

    html5 获取坐标: <!DOCTYPE HTML> <html> <head> <title>test1.html</title> &l ...

  6. 图片水平垂直居中(兼容IE6,IE7,firefox,opera,safari,其中图片可以是任何块元素)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. leetcode944

    public class Solution { public int MinDeletionSize(string[] A) { ; ; j < A[].Length; j++) { ; i & ...

  8. CSS 3栏自适应布局

    绝对定位 css html,body{margin: 0px;height:100%;} div{height: 100%;} .left,.right {top: 0px;position: abs ...

  9. 遍历Datatable

    //方法一 DataSet dataSet = new DataSet(); DataTable dt = dataSet.Tables[]; ; i < dt.Rows.Count; i++) ...

  10. focusin 事件| focusout事件

    focusin 定义和用法 当元素(或在其内的任意元素)获得焦点时发生 focusin 事件. 当在元素或在其内的任意元素上发生 focus 事件时,focusin() 方法添加要运行的函数. 与 f ...