`

MERGE函数的妙用案例

 
阅读更多

 

本文来至《剑破冰山》-Oracle开发艺术
/******************************************************************************
 *探索merge方法
 *
 *****************************************************************************/
 --1.what is merge?
 /*
 for exmple
 从T1表更新数据到T2表,如果T2表NAME字段的记录在T1表中存在,就将MONEY字段的值累加,如果不
 存在,将T1表的记录插入到T2表中。
 */
 DROP TABLE T1;
 CREATE TABLE t1(NAME VARCHAR2(20),money NUMBER);
 INSERT INTO t1 VALUES('A',100);
 INSERT INTO t1 VALUES('B',200);
 
 DROP TABLE t2;
 CREATE TABLE t2(NAME VARCHAR2(20),money NUMBER);
 INSERT INTO t2 VALUES('A',300);
 INSERT INTO t2 VALUES('C',100);
 COMMIT;
 
 SELECT * FROM t1;
 /*
  大家都知道,按照一般逻辑思路,该需求至少需要update和insert两条sql才能完成,
  如考虑在PL/SQL中用纯编程语言思路实现,则必须要考虑逻辑判断,这样就显得更麻烦了。
  merge语句的出现正是为了解决此类问题,使用merge语句,可以实现“存在则update,
  不存在则insert”的逻辑
 */
 --以下是使用merge语句简洁明了地单条实现该需求,如下:
MERGE INTO t2 USING t1 ON (t1.NAME=t2.NAME)
WHEN MATCHED THEN
  UPDATE SET t2.money = t1.money+t2.money WHEN NOT MATCHED THEN
  INSERT VALUES
    (t1.NAME,t1.money
    );
COMMIT;

SELECT * FROM t2;

/******************
merge的巧妙用法 
*******************/
/**
 案例1
 需求为:将如下TEST记录ID=1 的 NAME 改为 ID=2 的 NAME 值,
 将 ID=2 的 NAME 改为 ID=1 的 NAME 值
*/
DROP TABLE test;
CREATE TABLE test(ID NUMBER,NAME VARCHAR2(20));
INSERT INTO test VALUES(1,'a');
INSERT INTO test VALUES(2,'b');
COMMIT;
SELECT * FROM test;

--如果执行如下:
UPDATE test SET NAME =(SELECT NAME FROM test WHERE ID=2)WHERE ID =1;
--此时ID=1的NAME值已经变了,就不可能用如下代码来更新了。
UPDATE test SET NAME =(SELECT NAME FROM test WHERE ID=1)WHERE ID=2;

--如果是过程就很简单了,可以把原来的值先存储起来。但是是否但条件SQL一定不行呢?
--其实单条SQL是可以解决的,可以考虑灵活利用merge特性。可考虑先构造一个虚拟表T,
--然后再根据此虚拟表T和真实的TEST表进行merge更新,这样就方便快捷地完成了。
--1.构造虚拟表
SELECT 1 ID, (SELECT NAME FROM TEST WHERE ID = 2) NAME
  FROM DUAL
UNION ALL
SELECT 2, (SELECT NAME FROM TEST WHERE ID = 1) FROM DUAL;

--有了此思路,结合前面所学的merge知识,可以通过如下简洁的代码来完成更新。
MERGE INTO TEST
USING (SELECT 1 ID, (SELECT NAME FROM TEST WHERE ID = 2) NAME
         FROM DUAL
       UNION ALL
       SELECT 2, (SELECT NAME FROM TEST WHERE ID = 1) FROM DUAL
       
       ) T
ON (TEST.ID = T.ID)
WHEN MATCHED THEN
  UPDATE SET TEST.NAME = T.NAME
WHEN NOT MATCHED THEN
  INSERT VALUES (T.ID, T.NAME);

SELECT * FROM test;

--本案例用的是merge的方法,当然,其中构造虚拟表也是一个非常重要的思路,如果只是
--查询出改变后的结果而不是真实地进行更新,则可以不采用merge,直接采用如下方式
--取出结果
WITH t AS (
SELECT 1 ID, (SELECT NAME FROM TEST WHERE ID = 2) NAME
  FROM DUAL
UNION ALL
SELECT 2, (SELECT NAME FROM TEST WHERE ID = 1) FROM DUAL
)
SELECT TESt.ID, T.NAME FROM TEST, T WHERE TEST.ID = T.ID;

--案例2
--通过merge 可以得到一个非常有用的方法,就是只要检查出更新后的结果集,就可以
--利用该结果集来更新原表记录,即MERGE+ROWID方法

--案例2是案例1的延伸,改变了案例1的处理思路,不再采用构造虚拟表T来关联TEST表的方式,
--而是直接把真实结果用SELECT的方式取出,然后利用这个结果集更新原表记录。
MERGE INTO TEST
USING (WITH T AS (SELECT 1 ID, (SELECT NAME FROM TEST WHERE ID = 2) NAME
                    FROM DUAL
                  UNION ALL
                  SELECT 2, (SELECT NAME FROM TEST WHERE ID = 1) FROM DUAL)
  SELECT TEST.ID, TEST.ROWID AS RN, T.NAME
    FROM TEST, T
   WHERE T.ID = TEST.ID) N ON (TEST.ROWID = N.RN) WHEN MATCHED THEN
    UPDATE SET TEST.NAME = N.NAME
  WHEN NOT MATCHED THEN
    INSERT VALUES (N.ID, N.NAME);
SELECT * FROM test;

--后记
/******
 直接UPDATE一个子查询的写法也是可以的,但是却又很多限制,稍微复杂的查询就容易出错。
 此时用MERGE是最好的办法,结合ROWID的方法,可快速准确地利用一个已查询出的结果集来
 更新自己,是一个非常好的思路,希望对大家有借鉴。
****/ 
 
 

 

分享到:
评论

相关推荐

    php常用数组函数实例小结

    1. array array_merge(array $array1 [, array $array2 [, $array]]) 函数功能:将一个或多个数组的单元合并起来,一个数组中的值附加在前一个数组的后面。返回结果的数组。 如果输入的数组中有相同的字符串键名,...

    收获不止SQL优化

    第1章 全局在胸——用工具对SQL整体优化 1 1.1 都有哪些性能工具 1 1.1.1 不同调优场景分析 2 1.1.2 不同场景对应工具 2 1.2 整体性能工具的要点 4 1.2.1 五大性能报告的获取 5 1.2.2 五大报告关注的要点 10 ...

    收获,不止SQL优化--抓住SQL的本质

    第1章 全局在胸——用工具对SQL整体优化 1 1.1 都有哪些性能工具 1 1.1.1 不同调优场景分析 2 1.1.2 不同场景对应工具 2 1.2 整体性能工具的要点 4 1.2.1 五大性能报表的获取 5 1.2.2 五大报表关注的要点 10 ...

    《剑破冰山__Oracle开发艺术_》高清PDF

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫淡、管道函数的学习与实战应用、巧用锁特性避免...

    Python和Excel的结合应用: Python在数据分析中的使用离不开pandas库 pandas库经过多个版本的迭代优化

    还可以通过Python实现类似Excel中vlookup的功能,比如在Python中通过merge方法实现数据表的连接,从而实现近似查找等功能 1 。 PowerBI数据分析大师课: 这个课程是一个全面的PowerBI数据分析教程,包括基本数据处理...

    剑破冰山++Oracle开发艺术[1].part01

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part07

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part04

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part02

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part08

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part10

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part03

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part05

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part06

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山++Oracle开发艺术[1].part09

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山 Oracle开发艺术.part1.rar(共3part)

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山 Oracle开发艺术.part2.rar

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山 Oracle开发艺术.part3.rar (共3part)

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    C++大学教程,一本适合初学者的入门教材(part2)

    11.3.4 用成员函数put输出字符和put函数的连续调用 11.4 输入流 11.4.1 流读取运算符 11.4.2 成员函数get和getline 11.4.3 istream类中的其他成员函数(Peek、Putback和ignore) 11.4.4 类型安全的I/0 ...

Global site tag (gtag.js) - Google Analytics