Oracle基础之Merge into

  Merge into语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句。

   通过MERGE语句,根据一张表或多表联合查询的连接条件对另外一张表进行查询,连接条件匹配上的进行UPDATE,无法匹配的执行INSERT。

  这个语法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE。通过这个MERGE你能够在一个SQL语句中对一个表同时执行INSERT和UPDATE操作. 在 Oracle 10g中MERGE有一些新特性,后面我会介绍这些新特征。先看看MERGE语法如下:

MERGE INTO TEST_NEW DM USING
(
        SELECT DATE_CD,
               HR_CD,
               DATE_HR,
               DECODE(GROUPING(CITY_ID), 1, 9999, CITY_ID) AS CITY_ID,
               DECODE(GROUPING(SYSTEM_ID), 1, -9999, SYSTEM_ID) AS SYSTEM_ID,
               SUM(GSM_REG_USERCNT) AS GSM_REG_USERCNT,
               SUM(TD_REG_USERCNT) AS TD_REG_USERCNT,
               SUM(TD_REG_USERRAT) AS TD_REG_USERRAT,
               SUM(GSM_POWERON_USERCNT) AS GSM_POWERON_USERCNT,
               SUM(TD_POWERON_USERCNT) AS TD_POWERON_USERCNT,
               SUM(TD_POWERON_USERRAT) AS TD_POWERON_USERRAT
        FROM   TEST_OLD
         GROUP BY DATE_HR, DATE_CD, HR_CD, ROLLUP(SYSTEM_ID),ROLLUP(CITY_ID)
) TMP
ON
(
                DM.DATE_CD   = TMP.DATE_CD
            AND DM.HR_CD     = TMP.HR_CD
            AND DM.CITY_ID   = TMP.CITY_ID
            AND DM.SYSTEM_ID = TMP.SYSTEM_ID
)
WHEN MATCHED THEN  UPDATE  SET
      DM.GSM_REG_USERCNT = TMP.GSM_REG_USERCNT,
      DM.TD_REG_USERCNT = TMP.TD_REG_USERCNT,
      DM.TD_REG_USERRAT = TMP.TD_REG_USERRAT,
      DM.GSM_POWERON_USERCNT  = TMP.GSM_POWERON_USERCNT,
      DM.TD_POWERON_USERCNT = TMP.TD_POWERON_USERCNT,
      DM.TD_POWERON_USERRAT = TMP.TD_POWERON_USERRAT,
      DM.DATE_HR = TMP.DATE_HR
WHEN NOT MATCHED THEN
INSERT
(
      DM.DATE_CD,
      DM.HR_CD,
      DM.DATE_HR,
      DM.CITY_ID,
      DM.SYSTEM_ID,
      DM.GSM_REG_USERCNT,
      DM.TD_REG_USERCNT,
      DM.TD_REG_USERRAT,
      DM.GSM_POWERON_USERCNT,
      DM.TD_POWERON_USERCNT,
      DM.TD_POWERON_USERRAT
)
VALUES
(
      TMP.DATE_CD,
      TMP.HR_CD,
      TMP.DATE_HR,
      TMP.CITY_ID,
      TMP.SYSTEM_ID,
      TMP.GSM_REG_USERCNT,
      TMP.TD_REG_USERCNT,
      TMP.TD_REG_USERRAT,
      TMP.GSM_POWERON_USERCNT,
      TMP.TD_POWERON_USERCNT,
      TMP.TD_POWERON_USERRAT);

  WHEN MATCHED THEN UPDATE SET  表示当on里面的关键字匹配上的时候,就进行修改操作。

  但是值得注意的是,在做修改操作的时候,不可以修改on里面关键字的值。

  WHEN NOT MATCHED THEN INSERT 表示当on里面的关键字匹配不上的时候,也就是说没有这样一条记录存在TEST_NEW表中时,就进行新增操作。

  这时,做新增操作,就可以将on里面的字段进行设置值。

  在ORACLE 10i中,MERGE有如下一些新特性。

1、UPDATE或INSERT子句是可选的   

  假如某个系统中,有个订单表,现在要求新增订单的记录都要反应到订单历史表ORDER_HISTORY中,我们可以如下写脚本:

MERGE INTO ORDER_HISTORY H USING
(
      SELECT ORDER_ID               ,--订单编号
             CUSTOMER_ID            ,--客户编号
             EMPLOYEE_ID            ,--员工编号
             ORDER_DATE             ,--订购日期;
             REQUIRED_DATE          ,--预计到达日期
             SHIPPED_DATE           ,--发货日期
             SHIPPER                ,--运货商
             FREIGHT                ,--运费
             SHIP_NAM               ,--货主姓名;
             SHIP_ADDRESS           ,--货主地址
             SHIP_CITY              ,--货主所在城市;
             SHIP_REGION            ,--货主所在地区;
             SHIP_POSTALCODE        ,--货主邮编
             SHIP_COUNTRY            --货主所在国家
      FROM  ORDER_DTL
      WHERE TO_CHAR(ODER_DATE, ‘YYYY-MM-DD‘) = ‘20110530‘
) O
ON
(
            O.ORDER_ID = H.ORDER_ID
)
WHEN NOT MATCHED THEN INSERT
(
             H.ORDER_ID               ,
             H.CUSTOMER_ID            ,
             H.EMPLOYEE_ID            ,
             H.ORDER_DATE             ,
             H.REQUIRED_DATE          ,
             H.SHIPPED_DATE           ,
             H.SHIPPER                ,
             H.FREIGHT                ,
             H.SHIP_NAM               ,
             H.SHIP_ADDRESS           ,
             H.SHIP_CITY              ,
             H.SHIP_REGION            ,
             H.SHIP_POSTALCODE        ,
             H.SHIP_COUNTRY
)
VALUES
(
            O.ORDER_ID                ,
            O.CUSTOMER_ID             ,
            O.EMPLOYEE_ID             ,
            O.ORDER_DATE              ,
            O.REQUIRED_DATE           ,
            O.SHIPPED_DATE            ,
            O.SHIPPER                 ,
            O.FREIGHT                 ,
            O.SHIP_NAM                ,
            O.SHIP_ADDRESS            ,
            O.SHIP_CITY               ,
            O.SHIP_REGION             ,
            O.SHIP_POSTALCODE         ,
            O.SHIP_COUNTRY);

  

  从上可以看出,MATCHED 或NOT MATCHED是可选的。不必非得

  WHEN NOT MATCHED THEN UPDATE SET

  .....

  WHEN MATCHED THEN INSERT

2、UPDATE和INSERT子句可以加WHERE子句

  现在由于需求改变,我们仅仅需要把员工1001的订单数据同步到订单历史记录表

MERGE INTO ORDER_HISTORY H USING
(
      SELECT ORDER_ID               ,--订单编号
             CUSTOMER_ID            ,--客户编号
             EMPLOYEE_ID            ,--员工编号
             ORDER_DATE             ,--订购日期;
             REQUIRED_DATE          ,--预计到达日期
             SHIPPED_DATE           ,--发货日期
             SHIPPER                ,--运货商
             FREIGHT                ,--运费
             SHIP_NAM               ,--货主姓名;
             SHIP_ADDRESS           ,--货主地址
             SHIP_CITY              ,--货主所在城市;
             SHIP_REGION            ,--货主所在地区;
             SHIP_POSTALCODE        ,--货主邮编
             SHIP_COUNTRY            --货主所在国家
      FROM   ORDER_DTL
) O
ON
(
            O.ORDER_ID = H.ORDER_ID
)
WHEN MATCHED THEN UPDATE    SET
             H.CUSTOMER_ID         =     O.CUSTOMER_ID       ,
             H.EMPLOYEE_ID         =     O.EMPLOYEE_ID       ,
             H.ORDER_DATE          =     O.ORDER_DATE        ,
             H.REQUIRED_DATE       =     O.REQUIRED_DATE     ,
             H.SHIPPED_DATE        =     O.SHIPPED_DATE      ,
             H.SHIPPER             =     O.SHIPPER           ,
             H.FREIGHT             =     O.FREIGHT           ,
             H.SHIP_NAM            =     O.SHIP_NAM          ,
             H.SHIP_ADDRESS        =     O.SHIP_ADDRESS      ,
             H.SHIP_CITY           =     O.SHIP_CITY         ,
             H.SHIP_REGION         =     O.SHIP_REGION       ,
             H.SHIP_POSTALCODE     =     O.SHIP_POSTALCODE   ,
             H.SHIP_COUNTRY        =     O.SHIP_COUNTRY
       WHERE O.EMPLOYEE_ID = ‘1001‘
WHEN NOT MATCHED THEN INSERT
(
             H.ORDER_ID               ,
             H.CUSTOMER_ID            ,
             H.EMPLOYEE_ID            ,
             H.ORDER_DATE             ,
             H.REQUIRED_DATE          ,
             H.SHIPPED_DATE           ,
             H.SHIPPER                ,
             H.FREIGHT                ,
             H.SHIP_NAM               ,
             H.SHIP_ADDRESS           ,
             H.SHIP_CITY              ,
             H.SHIP_REGION            ,
             H.SHIP_POSTALCODE        ,
             H.SHIP_COUNTRY
)
VALUES
(
            O.ORDER_ID                ,
            O.CUSTOMER_ID             ,
            O.EMPLOYEE_ID             ,
            O.ORDER_DATE              ,
            O.REQUIRED_DATE           ,
            O.SHIPPED_DATE            ,
            O.SHIPPER                 ,
            O.FREIGHT                 ,
            O.SHIP_NAM                ,
            O.SHIP_ADDRESS            ,
            O.SHIP_CITY               ,
            O.SHIP_REGION             ,
            O.SHIP_POSTALCODE         ,
            O.SHIP_COUNTRY
)   WHERE O.EMPLOYEE_ID = ‘1001‘;

  

时间: 2024-10-07 10:21:42

Oracle基础之Merge into的相关文章

【转载:Oracle基础知识】Oracle数据库体系结构

先来看张直观的图:                                            oracle 11g 体系结构图 理解Oracle体系结构要充分理解三个概念:数据库(database),数据库实例(instance),会话(session),一定不要把这三个概念弄混. 数据库的概念 (A)    物理存储结构由数据文件.控制文件.重做日志文件组成: 1.       数据文件(datafile) select * from dba_data_files; 数据文件包括存

Oracle基础实训

一.Oracle基础SQL练习 班级表:班级编号(主键.标识列).班级名称.班主任.开班日期老师表:老师编号(主键.标识列) .姓名.性别(默认值‘男’).身份证号(必须是18位数字).联系电话学生表:学号(主键.固定五位数字) .班级编号.姓名.性别.出生日期.联系电话.家庭地址成绩表:编号(主键.标识列) .学号.科目名称.分数 1.表格创建 create table();语法 CREATE TABLE [schema.]table (column datatype [DEFAULT exp

Oracle基础知识笔记(10) 约束

大清早打开vs2008,出现这么诡异的错, 删了一个dll的就好了.如图 Oracle基础知识笔记(10) 约束

Oracle基础 shutdown和startup

原文:Oracle基础 shutdown和startup 一.shutdown命令:SHUTDOWN有四个参数:NORMAL.TRANSACTIONAL.IMMEDIATE.ABORT.缺省不带任何参数时表示是NORMAL. SHUTDOWN NORMAL:不允许新的连接.等待会话结束.等待事务结束.做一个检查点并关闭数据文件.启动时不需要实例恢复. SHUTDOWN TRANSACTIONAL:不允许新的连接.不等待会话结束.等待事务结束.做一个检查点并关闭数据文件.启动时不需要实例恢复. S

Oracle基础学习3--Oracle创建用户并授权

Oracle服务器端的操作一般如下: 1)       安装Oracle服务器软件 2)       创建数据库(安装时自动创建) 3)       配置监听(安装时自动配置) 4)       启动Oracle实例 5)       创建用户表空间 6)       创建新用户并授权 下面就开始讲创建用户表空间.创建新用户并授权两项: 首先要用系统管理员登陆Oracle(sqlplus/as sysdba) ?  创建用户表空间(D盘根目录创建名为ts_zhangsan的表空间) create

Oracle基础 数据库备份和恢复

原文:Oracle基础 数据库备份和恢复 一.为什么需要数据备份 造成数据丢失的主要原因: 1.介质故障. 2.用户的错误操作. 3.服务器的彻底崩溃. 4.计算机病毒. 5.不可预料的因素. Oracle中故障类型分为以下4种. 1.语句故障: 执行SQL语句过程发生的逻辑故障可导致语句故障.如果用户编写的SQL语句无效,就会发生语句故障.Oracle可自我修复语句故障,撤销语句产生的而印象,并将控制权交给应用程序. 2.用户进程故障 当用户程序出错而无法访问Oracle数据库时,就会发生用户

Oracle基础知识笔记(11) 建表、更新、查询综合练习

有某个学生运动会比赛信息的数据库,保存了如下的表: 运动员sporter(运动员编号sporterid,运动员姓名name,运动员性别sex,所属系号department) 项目item(项目编号itemid,项目名称itemname,项目比赛地点location) 成绩grade(运动员编号id,项目编号itemid,积分mark) 请用SQL语句完成如下功能: 1.  建表,并在相应字段上增加约束: 定义各个表的主键和外键约束: 运动员的姓名和所属系别不能为空: 积分要第为空值,要么为6,4

Oracle基础学习1--Oracle安装

安装过程较简单,按着步骤走即可.这里需要提醒如果要使用PL/SQL来操作Oracle,那么最好安装32位Oracle程序.原因是网上说PL/SQL只对32位Oracle进行支持,如果用64为Oracle+PL/SQL协同工作,会出现许多问题,例如无法加载oci.dll等.自己当然也亲自经历过,64位的Oracle单独使用很好,但相应的PL/SQL Developer却较难配置. 安装过程需要注意两个地方: ?  全局数据库名: ?  系统用户的密码(一般默认即可) 如何验证安装成功?按着自己的经

Oracle基础及三层分页查询

一.数据库表空间和数据文件 解析:一个数据库下可以开N个表空间,一个表空间可以包含N个数据文件.表空间是逻辑概念. 二.关于listener.ora位置 修改该界面上的数据,会影响指定路径的监听配置文件 D:\app\asus\product\11.2.0\dbhome_2\NETWORK\ADMIN 三.数据库和实例的关系 数据库(database):物理操作系统文件或磁盘(disk)的集合.使用Oracle 10g的自动存储管理(Automatic Storage Management,AS