Oracle-merge用法详解

来源:未知 责任编辑:智问网络 发表时间:2013-10-22 19:29 点击:

Oracle9i引入了MERGE命令,你能够在一个SQL语句中对一个表同时执行inserts和updates操作. MERGE命令从一个或多个数据源中选择行来updating或inserting到一个或多个表.在Oracle 10g中MERGE有如下一些改进:

 

 

你能够添加WHERE子句到UPDATE或INSERT子句中去, 来跳过update或insert操作对某些行的处理. 下面例子根据表NEWPRODUCTS来更新表PRODUCTS数据, 但必须字段CATEGORY也得同时匹配上:

 

 DE>SQL> MERGE INTO products p

    2 USING newproducts np

    3 ON (p.product_id = np.product_id)

    4 WHEN MATCHED THEN

    5 UPDATE

    6 SET p.product_name = np.product_name

    7 WHERE p.category = np.category;

 

    2 rows merged.

 

    SQL> SELECT * FROM products;

 

    PRODUCT_ID PRODUCT_NAME CATEGORY

    ---------- -------------------- ----------

    1501 VIVITAR 35MM ELECTRNCS

    1502 OLYMPUS CAMERA ELECTRNCS

    1600 PLAY GYM TOYS

    1601 LAMAZE TOYS

    1666 HARRY POTTER DVD

    SQL>

    SQL> rollback;DE>

 

 

 

在这个例子中, 产品ID为1502,1601和1666匹配ON条件但是1666的category不匹配. 因此MERGE命令只更新两行数据. 下面例子展示了在Updates和Inserts子句都使用WHERE子句:

 

 DE>SQL> MERGE INTO products p

    2 USING newproducts np

    3 ON (p.product_id = np.product_id)

    4 WHEN MATCHED THEN

    5 UPDATE

    6 SET p.product_name = np.product_name,

    7 p.category = np.category

    8 WHERE p.category = 'DVD'

    9 WHEN NOT MATCHED THEN

    10 INSERT

    11 VALUES (np.product_id, np.product_name, np.category)

    12 WHERE np.category != 'BOOKS'

    SQL> /

 

    1 row merged.

 

    SQL> SELECT * FROM products;

 

    PRODUCT_ID PRODUCT_NAME CATEGORY

    ---------- -------------------- ----------

    1501 VIVITAR 35MM ELECTRNCS

    1502 OLYMPUS IS50 ELECTRNCS

    1600 PLAY GYM TOYS

    1601 LAMAZE TOYS

    1666 HARRY POTTER TOYS

 

    SQL>DE>

 

 

注意由于有WHERE子句INSERT没有插入所有不匹配ON条件的行到表PRODUCTS.

3、无条件的Inserts

 

你能够不用连接源表和目标表就把源表的数据插入到目标表中. 这对于你想插入所有行到目标表时是非常有用的. Oracle 10g现在支持在ON条件中使用常量过滤谓词. 举个常量过滤谓词例子ON (1=0). 下面例子从源表插入行到表PRODUCTS, 不检查这些行是否在表PRODUCTS中存在:

 

 

 

 

 

 

 

 

 DE>SQL> MERGE INTO products p

    2 USING newproducts np

    3 ON (1=0)

    4 WHEN NOT MATCHED THEN

    5 INSERT

    6 VALUES (np.product_id, np.product_name, np.category)

    7 WHERE np.category = 'BOOKS'

    SQL> /

 

    1 row merged.

 

    SQL> SELECT * FROM products;

 

    PRODUCT_ID PRODUCT_NAME CATEGORY

    ---------- -------------------- ----------

    1501 VIVITAR 35MM ELECTRNCS

    1502 OLYMPUS IS50 ELECTRNCS

    1600 PLAY GYM TOYS

    1601 LAMAZE TOYS

    1666 HARRY POTTER DVD

    1700 WAIT INTERFACE BOOKS

    6 rows selected.

    SQL>DE>

 

 

 

4、新增加的DELETE子句

 

Oracle 10g中的MERGE提供了在执行数据操作时清除行的选项. 你能够在WHEN MATCHED THEN UPDATE子句中包含DELETE子句. DELETE子句必须有一个WHERE条件来删除匹配某些条件的行.匹配DELETE WHERE条件但不匹配ON条件的行不会被从表中删除.

 

下面例子验证DELETE子句. 我们从表NEWPRODUCTS中合并行到表PRODUCTS中, 但删除category为ELECTRNCS的行.

 

 DE>SQL> MERGE INTO products p

    2 USING newproducts np

    3 ON (p.product_id = np.product_id)

    4 WHEN MATCHED THEN

    5 UPDATE

    6 SET p.product_name = np.product_name,

    7 p.category = np.category

    8 DELETE WHERE (p.category = 'ELECTRNCS')

    9 WHEN NOT MATCHED THEN

    10 INSERT

    11 VALUES (np.product_id, np.product_name, np.category)

    SQL> /

 

    4 rows merged.

 

    SQL> SELECT * FROM products;

 

    PRODUCT_ID PRODUCT_NAME CATEGORY

    ---------- -------------------- ----------

    1501 VIVITAR 35MM ELECTRNCS

    1600 PLAY GYM TOYS

    1601 LAMAZE TOYS

    1666 HARRY POTTER TOYS

    1700 WAIT INTERFACE BOOKS

    SQL>DE>

 

 

 

产品ID为1502的行从表PRODUCTS中被删除, 因为它同时匹配ON条件和DELETE WHERE条件. 产品ID为1501的行匹配DELETE WHERE条件但不匹配ON条件, 所以它没有被删除. 产品ID为1700 的行不匹配ON条件, 所以被插入表PRODUCTS. 产品ID为1601和1666的行匹配ON条件但不匹配DELETE WHERE条件, 所以被更新为表NEWPRODUCTS中的值.

 

例子二:

Merge Into 语句代替Insert/Update在Oracle中的应用实战

动机:

想在Oracle中用一条SQL语句直接进行Insert/Update的操作。

说明:

在进行SQL语句编写时,我们经常会遇到大量的同时进行Insert/Update的语句 ,也就是说当存在记录时,就更新(Update),不存在数据时,就插入(Insert)。

实战:

接下来我们有一个任务,有一个表T,有两个字段a,b,我们想在表T中做Insert/Update,如果存在,则更新T中b的值,如果不存在,则插入一条记录。在Microsoft的SQL语法中,很简单的一句判断就可以了,SQL Server中的语法如下:

if exists(select 1 from T where T.a='1001' ) update T set T.b=2 Where T.a='1001' else insert into T(a,b) values('1001',2);

以上语句表明当T表中如果存在a='1001' 的记录的话,就把b的值设为2,否则就Insert一条a='100',b=2的记录到T中。

但是接下来在Oracle中就遇到麻烦了,记得在Oracle 9i之后就有一条Merge into 的语句可以同时进行Insert 和Update的吗,Merge的语法如下:

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 INTO T T1

USING (SELECT a,b FROM T WHERE t.a='1001') T2

ON ( T1.a=T2.a)

WHEN MATCHED THEN

  UPDATE SET T1.b = 2

WHEN NOT MATCHED THEN

  INSERT (a,b) VALUES('1001',2);

以上的语句貌似很对是吧,实际上,该语句只能进行更新,而无法进行Insert,错误在哪里呢?

其实在Oracle中Merge语句原先是用来进行整表的更新用的,也就是ETL工具比较常用的语法,重点是在Using上。

用中文来解释Merge语法,就是:

在alias2中Select出来的数据,每一条都跟alias1进行ON (join condition)的比较,如果匹配,就进行更新的操作(Update),如果不匹配,就进行插入操作(Insert)。

因此,严格意义上讲,”在一个同时存在Insert和Update语法的Merge语句中,总共Insert/Update的记录数,就是Using语句中alias2的记录数。”

以上这句话也就很好的解释了在上面写的语句为何只能进行Update,而不能进行Insert了,因为都Select不到数据,如何能进行Insert呢:)

接下来要改成正确的语句就容易多了,如下:

MERGE INTO T T1

USING (SELECT '1001' AS a,2 AS b FROM dual) T2

ON ( T1.a=T2.a)

WHEN MATCHED THEN

  UPDATE SET T1.b = T2.b

WHEN NOT MATCHED THEN

  INSERT (a,b) VALUES(T2.a,T2.b);

查询结果,OK!

注意:

如果不懂Merge语句的原理,Merge语句是一条比较危险的语句,特别是在您只想更新一条记录的时候,因为不经意间,你可能就把整表的数据都Update了一遍.....汗!!!

我曾经犯过的一个错误如下所示,大家看出来是什么问题了吗?

MERGE INTO T T1

USING (SELECT Count(*) cnt FROM T WHERE T.a='1001') T2

ON (T2.cnt>0)

WHEN MATCHED THEN

  UPDATE SET T1.b = T2.b

WHEN NOT MATCHED THEN

  INSERT (a,b) VALUES(T2.a,T2.b);

 

1、UPDATE或INSERT子句是可选的

 

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

 

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

 

4、UPDATE子句后面可以跟DELETE子句来去除一些不需要的行

 

首先创建示例表:

 

 DE>create table PRODUCTS

    (

    PRODUCT_ID INTEGER,

    PRODUCT_NAME VARCHAR2(60),

    CATEGORY VARCHAR2(60)

    );

 

    insert into PRODUCTS values (1501, 'VIVITAR 35MM', 'ELECTRNCS');

    insert into PRODUCTS values (1502, 'OLYMPUS IS50', 'ELECTRNCS');

    insert into PRODUCTS values (1600, 'PLAY GYM', 'TOYS');

    insert into PRODUCTS values (1601, 'LAMAZE', 'TOYS');

    insert into PRODUCTS values (1666, 'HARRY POTTER', 'DVD');

    commit;

 

    create table NEWPRODUCTS

    (

    PRODUCT_ID INTEGER,

    PRODUCT_NAME VARCHAR2(60),

    CATEGORY VARCHAR2(60)

    );

 

    insert into NEWPRODUCTS values (1502, 'OLYMPUS CAMERA', 'ELECTRNCS');

    insert into NEWPRODUCTS values (1601, 'LAMAZE', 'TOYS');

    insert into NEWPRODUCTS values (1666, 'HARRY POTTER', 'TOYS');

    insert into NEWPRODUCTS values (1700, 'WAIT INTERFACE', 'BOOKS');

    commit;DE>

1、可省略的UPDATE或INSERT子句

 

在Oracle 9i, MERGE语句要求你必须同时指定INSERT和UPDATE子句.而在Oracle 10g, 你可以省略UPDATE或INSERT子句中的一个. 下面的例子根据表NEWPRODUCTS的PRODUCT_ID字段是否匹配来updates表PRODUCTS的信息:

 

 

 DE>SQL> MERGE INTO products p

    2 USING newproducts np

    3 ON (p.product_id = np.product_id)

    4 WHEN MATCHED THEN

    5 UPDATE

    6 SET p.product_name = np.product_name,

    7 p.category = np.category;

 

    3 rows merged.

 

    SQL> SELECT * FROM products;

 

    PRODUCT_ID PRODUCT_NAME CATEGORY

    ---------- -------------------- ----------

    1501 VIVITAR 35MM ELECTRNCS

    1502 OLYMPUS CAMERA ELECTRNCS

    1600 PLAY GYM TOYS

    1601 LAMAZE TOYS

    1666 HARRY POTTER TOYS

    SQL>

    SQL> ROLLBACK;

    Rollback complete.

    SQL>DE>

 

 

 

在上面例子中, MERGE语句影响到是产品id为1502, 1601和1666的行. 它们的产品名字和种 类被更新为表newproducts中的值. 下面例子省略UPDATE子句, 把表NEWPRODUCTS中新的PRODUCT_ID插入到表PRODUCTS中, 对于在两个表中能够匹配上PRODUCT_ID的数据不作任何处理. 从这个例子你能看到PRODUCT_ID=1700的行被插入到表PRODUCTS中.

 

 DE>SQL> MERGE INTO products p

    2 USING newproducts np

    3 ON (p.product_id = np.product_id)

    4 WHEN NOT MATCHED THEN

    5 INSERT

    6 VALUES (np.product_id, np.product_name,

    7 np.category);

 

    1 row merged.

 

    SQL> SELECT * FROM products;

 

    PRODUCT_ID PRODUCT_NAME CATEGORY

    ---------- -------------------- ----------

    1501 VIVITAR 35MM ELECTRNCS

    1502 OLYMPUS IS50 ELECTRNCS

    1600 PLAY GYM TOYS

    1601 LAMAZE TOYS

    1666 HARRY POTTER DVD

    1700 WAIT INTERFACE BOOKSDE>

2、带条件的Updates和Inserts子句

    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • Table函数使用简介
    • Oracle数据库Constraint约束的常用操作及异常处理
    • Bulk Collect性能分析(zz)
    • export/import的使用
    • OCP043第十五讲 Database Security
    • ORACLE10gr2数据导入MySQL方案
    • oracle 让sys用户可以使用isqlplus
    • 在oracle数据库下使用iSQL*Plus DBA访问数据库
    • Oracle行列转换小结
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1