用merge 语句代替 insert 和delete

本文通过一个详细的示例介绍了 Oracle 数据库中 MERGE 语句的使用方法,包括如何实现更新和插入操作。同时提供了存储过程的创建及执行流程,展示了如何同步源表与目标表的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Oracle merge语句
前一段时间优化一个存储过程,用到了merge语句,现在再来举一个稍微详细点的例子。
merge语句可以起到update and insert功能,并且在一条语句中实现。语法如下:

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;

实例:
13:32:55 SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

13:33:04 SQL>  create table dept_test as select * from dept where 1=2;

表已创建。

建立测试procudere
13:33:08 SQL> Create Or Replace Procedure merge_dept
13:34:14   2  Is
13:34:14   3  Begin
13:34:14   4  Merge Into dept_test a
13:34:14   5  Using (Select deptno,
13:34:14   6                dname,
13:34:14   7                loc
13:34:14   8           From dept
13:34:14   9           ) b
13:34:14  10  On (a.deptno=b.deptno)
13:34:14  11  When Matched Then
13:34:14  12  Update Set a.dname=b.dname, /*a.deptno=b.deptno  注意不要更新on 对应的列 */
13:34:14  13         a.loc=b.loc
13:34:14  14  When Not Matched Then
13:34:14  15  Insert (deptno,
13:34:14  16          dname,
13:34:14  17          loc)
13:34:14  18  Values (b.deptno,
13:34:14  19          b.dname,
13:34:14  20          b.loc
13:34:14  21          )
13:34:14  23          ;
13:34:14  24  dbms_output.put_line('successful!!!');
13:34:14  25  Commit;
13:34:14  26  exception
13:34:14  27  when Others Then
13:34:14  28  dbms_output.put_line('unsccessful!!!');
13:34:14  29  End merge_dept;
13:34:17  30  /
过程已创建。
13:34:19 SQL>
执行过程,测试如下:
13:34:19 SQL> set serveroutput on;
13:38:05 SQL> select count(*) from dept_test;

  COUNT(*)
----------
         0
13:38:13 SQL> exec merge_dept;
successful!!!

PL/SQL 过程已成功完成。
13:38:55 SQL> select * from dept_test;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
结果dept和dept_test的数据一致
继续测试,

13:39:33 SQL> delete dept where rownum<2;

已删除 1 行。
13:39:41 SQL> update dept set loc='test' where deptno='30';
已更新 1 行。
13:39:59 SQL> commit;
提交完成。

13:40:01 SQL>  exec merge_dept;
successful!!!
PL/SQL 过程已成功完成。

13:40:07 SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        30 SALES          test
        40 OPERATIONS     BOSTON

13:40:13 SQL> select * from dept_test;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        30 SALES          test
        20 RESEARCH       DALLAS
        40 OPERATIONS     BOSTON

13:40:19 SQL>
可以看到,dept中update的记录在dept_test中也同样变更过来了,但是
delete的记录不会同步。此外用merge语句常出的一个错误就是update子
句中有on条件关联列,这样oracle会报错的,把关联条件的列从update子
句中移去即可(当when matched 的话,on 条件的二个字段肯定要一样)
,以上是在oracle9i环境下测试,

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10159839/viewspace-163514/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10159839/viewspace-163514/

### Oracle `MERGE INTO` 语句概述 在Oracle数据库中,`MERGE INTO`语句允许在一个原子操作中执行插入、更新甚至有条件地删除记录。此特性自Oracle 9i版本起被引入[^3]。 ### 使用 `MERGE INTO` 进行插入删除的操作指南 #### 基本语法结构 ```sql MERGE INTO target_table t USING source_table s ON (join_condition) WHEN MATCHED THEN UPDATE SET column1 = value1 [, column2 = value2 ...] DELETE WHERE condition WHEN NOT MATCHED THEN INSERT (column_list) VALUES (value_list); ``` - **target_table**: 被合并的目标表。 - **source_table**: 提供数据用于比较并可能触发插入或更新动作的数据源表。 - **join_condition**: 定义目标表与源表之间匹配关系的条件表达式。 - **UPDATE SET...**: 当找到匹配项时应用的列赋值列表。 - **DELETE WHERE...**: 可选子句,在满足特定条件下移除已存在的行[^2]。 - **INSERT (...)**: 如果未发现任何匹配,则向目标表添加新纪录。 请注意,并是所有的数据库版本都支持`DELETE`选项;这取决于具体的Oracle发行版及其配置情况。 #### 实际案例展示 假设存在两个表格:`employees`作为目标表以及临时加载员工变动信息的`new_employees`作为源表。下面的例子展示了如何利用`MERGE INTO`来同步这两张表中的数据: ```sql MERGE INTO employees e USING new_employees ne ON (e.employee_id = ne.employee_id) WHEN MATCHED THEN UPDATE SET salary = ne.salary, department_id = ne.department_id DELETE WHERE ne.status = 'terminated' WHEN NOT MATCHED THEN INSERT (employee_id, first_name, last_name, email, hire_date, job_id, salary, commission_pct, manager_id, department_id) VALUES (ne.employee_id, ne.first_name, ne.last_name, ne.email, sysdate, ne.job_id, ne.salary, ne.commission_pct, ne.manager_id, ne.department_id); ``` 这段SQL脚本会检查每一个来自`new_employees`的新条目是否已经在`employees`里有对应的记录。如果有对应记录并且状态标记为终止(`'terminated'`)则会被删除;如果只是简单的属性变化(比如薪水调整),那么就只做相应的字段更新。对于那些完全存在于现有雇员名单上的新人,则直接加入到正式人员编制之中[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值