1. 程式人生 > >Oracle SQL 1 : Oracle MERGE INTO Statement

Oracle SQL 1 : Oracle MERGE INTO Statement

1. 功能

根據源查詢的結果及相關條件,對目標物件執行DML操作,如INSERT/UPDATE/DELETE


2. 語法

MERGE INTO target_table
USING source_set
ON	(condition)
WHEN MATCHED THEN			//condition 滿足的話,就執行 statement1
insert/update/delete statement1
WHEN NOT MATCHED THEN
insert/update/delete statement2;	//condition 不滿足的話,就執行 statement2

3. 簡單例子
create table a1(a number);
insert into a1 values(1);	 
insert into a1 values(2);
insert into a1 values(3);
commit;

create table a2(a number, b number);
insert into a2 values(3, 4);
commit;

照著語法寫一個。
merge into a2
using a1
on (a2.a = a1.a)
when matched then
update set b = 1000
when not matched then 
insert (a2.b) values(100)

根據語法和兩個表中的資料來做進一步分析,a2.a = a1.a 也就是 兩個表中的a都等於3的時候就滿足,然後執行 update 語句,把 a2中的b重置成1000;接下來不 not matched 那一塊,執行 insert 語句,這時候 a1 中還有2條記錄,執行完之後, a2表也就變成 3 條記錄

SQL> select * from a2;

         A          B
---------- ----------
         3       1000
                  100
                  100


4、錯誤示例
一開始寫merge into 語句,可能會寫不對,幸運的是 oracle 會提供報錯資訊供參考,以下就是一個不正確的語句,多改幾次多執行幾次,會對 merge into 語句有進一步的認識的。

以下為錯誤語句

merge into a
using (select * from a1) a1
on a1.a > 0
when matched then
insert (a) values(a1.a) where a1.a=1
when a1.a > 3
update set a = a1.a
when not matched then 
delete where a > 3;

5、效率
根據語法來看,這個語句可以在一個語句裡面執行兩個以下的DML語句,在表掃描方面可以減少掃描次數,操作上也相應能夠提高效率,但是不好之處就是在於編寫這些條件可能需要一點時間,當然如果對業務很熟悉,寫起來也很容易。另外就是,如果表資料很大,可能需要多一點時間來執行該語句,這時候適當考慮換為單獨的DML 語句來執行,可能更有效率,畢竟凡事都不是絕對的。

6、其它示例

附上一個Oracle+SQL高階程式設計中的例子,例子寫得不錯,僅供參考。

/* Listing 1-20 */

create table dept60_bonuses
(employee_id number
,bonus_amt number);

insert into dept60_bonuses values (103, 0);

insert into dept60_bonuses values (104, 100);

insert into dept60_bonuses values (105, 0);

commit;

select employee_id, last_name, salary
from hr.employees
where department_id = 60 ;

select * from dept60_bonuses;

merge into dept60_bonuses b
using (
select employee_id, salary, department_id
from hr.employees
where department_id = 60) e
on (b.employee_id = e.employee_id)
when matched then
update set b.bonus_amt = e.salary * 0.2
where b.bonus_amt = 0
delete where (e.salary > 7500)
when not matched then
insert (b.employee_id, b.bonus_amt)
values (e.employee_id, e.salary * 0.1)
where (e.salary < 7500);

select * from dept60_bonuses;

rollback ;