merge into

动机:
   想在Oracle中用一条SQL语句直接进行Insert/Update的操作。
  说明:
  
在进行SQL语句编写时,我们经常会遇到大量的同时进行Insert/Update的语句
,也就是说当存在记录时,就更新(Update),不存在数据时,就插入(Insert)。
  merge into 是特有的功能,相当于在
MSSQL中的
  if exists(...)
   update table
  else
   Insert into
table.
  merge into 语法不仅没有if exists语法啰嗦,而且比if exists
还要高效很多。我经常用来在oracle之间同步数据库表。
  语法如下:
  MERGE INTO table_name
alias1 
  USING (table|view|sub_query) alias2 
  ON (join
condition) 
  WHEN MATCHED THEN 
  UPDATE
table_name 
  SET col1 = col_val1, 
  col2 =
col2_val 
  WHEN NOT MATCHED THEN 
  INSERT (column_list) VALUES
(column_values);
  
  如果不懂Merge语句的原理,Merge语句是一条比较危险的语句,特别是在您只想更新一条记录的时候,因为不经意间,你可能就把整表的数据都Update了一遍.....汗!!!
  ORACLE
9I中加入了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;
    创建测试数据表:
    create table tj_test(id number,name
varchar2(20),age number);
    向表中插入数据:
    insert into tj_test values
(1,‘jan‘,23);
    insert into tj_test values (2,‘kk‘,22);
    insert into
tj_test values (3,‘joe‘,27);
    select * from
tj_test;
    查询结果如下:
    1 jan 23
    2 kk 22
    3 joe
27
    创建另一新表
    create table tj_test1 as select * from tj_test where
1=0
    插入一条数据
    insert into tj_test1 values (1,‘jlk‘,23);
    select
* from tj_test1
    查询结果如下:
    1 jkl 23
--注意,这里的的NAME字段中的值是jkl
    使用MERGE,实现有则更新,无则插入,sql语句如下:
    merge into
tj_test1 tt1
    using tj_test tt
    on (tt1.id=tt.id)
    when
matched then
    update
set
    tt1.name=tt.name,
    tt1.age=tt.age
    when not matched
then
    insert
values(
    tt.id,
    tt.name,
    tt.age)
    查询tj_test1表(对比原来表中的数据,更新了ID=1
ROW中字段NAME,同时多出两条新数据)
    select * from tj_test1
    改变行数据如下:
    1 jan
23 --这里的原有jkl值被更新
    3 joe 27 --原来表中没有的插入
    2 kk 22
--原来表中没有的插入
    如果存在就更新,不存在就插入
    9i已经支持了,是Merge,但是只支持select子查询,
    如果是单条数据记录,可以写作select
…… from dual的子查询。
    语法为:
    MERGE INTO table
    USING
data_source
    ON (condition)
    WHEN MATCHED THEN
update_clause
    WHEN NOT MATCHED THEN insert_clause;
    如:
    MERGE
INTO course c
    USING (SELECT course_name,
period,
    course_hours
    FROM course_updates) cu
    ON
(c.course_name = cu.course_name
    AND c.period = cu.period)
    WHEN
MATCHED THEN
    UPDATE
    SET c.course_hours =
cu.course_hours
    WHEN NOT MATCHED THEN
    INSERT (c.course_name,
c.period,
    c.course_hours)
    VALUES (cu.course_name,
cu.period,
    cu.course_hours);

/*

Merge into 主要用作数据同步,把一张表中的数据同步到另一张表,可以用这个函数

*/

Merge是一个非常有用的功能,类似于Mysql里的insert into on duplicate
key. 

Oracle在9i引入了merge命令, 
通过这个merge你能够在一个SQL语句中对一个表同时执行inserts和updates操作.
当然是update还是insert是依据于你的指定的条件判断的,Merge into可以实现用B表来更新A表数据,如果A表中没有,则把B表的数据插入A表.
MERGE命令从一个或多个数据源中选择行来updating或inserting到一个或多个表 

语法如下 
MERGE
INTO [your table-name] [rename your table here] 
USING ( [write your
query here] )[rename your query-sql and using just like a table] 
ON
([conditional expression here] AND [...]...) 
WHEN MATHED THEN [here you
can execute some update sql or something else ] 
WHEN NOT MATHED THEN
[execute something else here ! ] 

我们先看看一个简单的例子,来介绍一个merge
into的用法 
merge into products p using newproducts np on (p.product_id =
np.product_id) 
when matched then 
update set p.product_name =
np.product_name 
when not matched then 
insert
values(np.product_id, np.product_name,
np.category) 

在这个例子里。前面的merger into products using newproducts
表示的用newproducts表来merge到products表,merge的匹配关系就是on后面的条件子句的内容,这里根据两个表的product_id来进行匹配,那么匹配上了我们的操作是就是when
matched then的子句里的动作了,这里的动作是update set p.product_name = np.product_name,
很显然就是把newproduct里的内容,赋值到product的product_name里。如果没有匹配上则insert这样的一条语句进去。
大家看看这个merget
inot的用法是不是一目了然了呀。这里merger的功能,好比比较,然后选择更新或者是插入,是一系列的组合拳,在做merge的时候,这样同样的情况下,merge的性能是优于同等功能的update/insert语句的。有人曾经分析merge是批量处理对性能贡献很大,个人觉得这个是没有考据的。 

我们也可以在using后面使用视图或者子查询。比如我们把newproducts换成 
merge
into products p using (select * from newproducts) np on (p.product_id =
np.product_id) 
when matched then 
update set p.product_name =
np.product_name 
when not matched then 
insert
values(np.product_id, np.product_name,
np.category) 
也是可以的。 

在Oracle
10g中MERGE有如下一些改进: 
1、UPDATE或INSERT子句是可选的 
2、UPDATE和INSERT子句可以加WHERE子句 
3、在ON条件中使用常量过滤谓词来insert所有的行到目标表中,不需要连接源表和目标表 
4、UPDATE子句后面可以跟DELETE子句来去除一些不需要的行 

我们通过实例来一一看看如上的新特性 

1.
UPDATE或INSERT子句是可选的 
在9i里由于必须insert
into和update都要存在,也就是不是update就是insert,不支持单一的操作,虽然还是可以曲线救国,呵呵
但是有些过于强势了。而10g里就是可选了,能符合我们更多的需求了 
比如上面的句子 
我们可以只存在update或者insert 
merge
into products p using newproducts np on (p.product_id =
np.product_id) 
when matched then 
update set p.product_name =
np.product_name 
这里,如果匹配就更新,不存在就不管了。 

2.
UPDATE和INSERT子句可以加WHERE子句 
这也是一个功能性的改进,能够符合我们更多的需求,这个where的作用很明显是一个过滤的条件,是我们加入一些额外的条件,对只对满足where条件的进行更新和insert 
merge
into products p using (select * from newproducts) np on (p.product_id =
np.product_id) 
when matched then 
update set p.product_name =
np.product_name where np.product_name like
‘OL%‘ 
这里表示只是对product_name开头是‘OL‘的匹配上的进行update,如果开头不是‘OL‘的就是匹配了也不做什么事情,insert里也可以加入where 
比如 
merge
into products p using (select * from newproducts) np on (p.product_id =
np.product_id) 
when matched then 
update set p.product_name =
np.product_name where np.product_name like ‘OL%‘ 
when not matched
then 
insert values(np.product_id, np.product_name, np.category) where
np.product_name like
‘OL%‘ 

这里注意比较一下,他们返回的结果行数,是有着差异的。 

3.
在ON条件中使用常量过滤谓词来insert所有的行到目标表中,不需要连接源表和目标表 

merge into products p
using (select * from newproducts) np on (1=0) 
when matched
then 
update set p.product_name = np.product_name 
when not
matched then 
insert values(np.product_id, np.product_name,
np.category) 
个人觉得这个功能没有太大的意义,我们的insert
into本身就支持这样的功能,没有必要使用merge 

4.
UPDATE子句后面可以跟DELETE子句来去除一些不需要的行 
delete只能和update配合,从而达到删除满足where条件的子句的纪录 
merge
into products p using (select * from newproducts) np on (p.product_id =
np.product_id) 
when matched then 
update set p.product_name =
np.product_name delete where p.product_id = np.product_id where np.product_name
like ‘OL%‘ 
when not matched then 
insert values(np.product_id,
np.product_name, np.category) 
这里我们达到的目的就是
会把匹配的记录的prodcut_name更新到product里,并且把product_name开头为OL的删除掉。

merge
into也是一个dml语句,和其他的dml语句一样需要通过rollback和commit
结束事务。 

Merge是一个非常强大的功能,而且是我们需求里经常会用到的一个有用的功能,所以我们一定要好好的学习到。 

文中需要的测试脚本在附件里提供下载。 
merge
into sample.sql

merge into,布布扣,bubuko.com

时间: 2024-10-15 04:53:47

merge into的相关文章

归并排序(Merge Sort)

更详细的请看这篇博文:http://www.cnblogs.com/jingmoxukong/p/4308823.html 我只做个人学习和补充 基于分治法的排序,比较简单.个人感觉其核心是数组左右拆分之后类似队列的比较.类似两两合并之类的算法都可以参考 分为3个步骤,拆开为树结构遍历->向上合并 特别做了一张gif来更好的理解归并排序 左边集合比较通过就左边索引前进,右边集合比较通过则右边索引前进 比较结果放入结果数组中 最后如果多出一个就把这一个直接加入结果数组 为了易于学习,代码直接使用了

Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. Subscribe to see which companies asked this question /** * Definition for singly-linked list. * struct ListN

LeetCode 21 Merge Two Sorted Lists

翻译 合并两个排好序的链表,并返回这个新链表. 新链表应该由这两个链表的头部拼接而成. 原文 Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 代码 /** * Definition for singly-linked list. * struct ListNode

LeetCode --- 88. Merge Sorted Array

题目链接:Merge Sorted Array Given two sorted integer arrays A and B, merge B into A as one sorted array. Note: You may assume that A has enough space (size that is greater or equal to m + n) to hold additional elements from B. The number of elements init

【leetcode】Merge k Sorted Lists

Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 采用优先队列priority_queue 把ListNode放入优先队列中,弹出最小指后,如果该ListNode有下一个元素,则把下一个元素放入到队列中 1 /** 2 * Definition for singly-linked list. 3 * stru

oracle查询转换_view merge

oracle对于子查询的支持做的很好,oracle optimizer会对inline view进行query transfomation,即视图合并,不过也经常带来意想不到的问题.下面是一个inline view的merge的例子: 1, 创建临时表 1 create table test1 as select * from dba_objects; 2 create table test2 as select * from dba_objects; 2, 以下查询语句 select * fr

LeetCode记录之21——Merge Two Sorted Lists

算法和数据结构这东西,真的是需要常用常练.这道看似简单的链表合并题,难了我好几个小时,最后还是上网搜索了一种不错算法.后期复习完链表的知识我会将我自己的实现代理贴上. 这个算法巧就巧在用了递归的思想,按照常规方法也能求得,但是就未免太复杂了. Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the fir

leetcode - Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x)

leetcode || 56、 Merge Intervals

problem: Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18]. Hide Tags Array Sort 题意:给定数组区间,合并有覆盖或者相邻的区间 thinking: (1)一開始我想到用hash table的方法,开一个总区间跨度的数组.对于有区间覆盖的数

elasticsearch index 之merge

merge是lucene的底层机制,merge过程会将index中的segment进行合并,生成更大的segment,提高搜索效率.segment是lucene索引的一种存储结构,每个segment都是一部分数据的完整索引,它是lucene每次flush或merge时候形成.每次flush就是将内存中的索引写出一个独立segment的过程.所以随着数据的不断增加,会形成越来越多的segment.因为segment是不可变的,删除操作不会改变segment内部数据,只是会在另外的地方记录某些数据删