oracle使用 merge 更新或插入数据

总结下。使用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);

上一篇:window10(64bit)+VS2010编译ACE_TAO源码库


下一篇:SQLite返回码