MERGE 函数的使用[通俗易懂]
1. MERGE是什么?
通過一個簡單的需求來了解MERGE 是什么?
從T1表更新數據到T2表,如果T2表NAME字段的記錄在T1表中存在,就將MONEY字段的值累加,
如果不存在,將T1表的記錄插入到T2表中。
CREATE TABLE T1(NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T1 VALUES (‘A’,10);
INSERT INTO T1 VALUES (‘B’,20);
COMMIT;
CREATE TABLE T2(NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T2 VALUES (‘A’,30);
INSERT INTO T2 VALUES (‘C’,20);
COMMIT;
如果按照一般邏輯思路,該需求至少需要UPDATE和INSERT兩條SQL語句才能完成,
但是使用MERGE語句,則可以實現“存在則UPDATE,不存在則INSERT”的邏輯。
MERGE 的語法:
MERGE INTO table [t.alias]
USING {table | view | subquery} [t.alias]
ON (condition)
WHEN MATCHED THEN
merge_updat_clause
WHEN NOT MATCHED THEN
merge_insert_clause;
注:USING后面必須包含要更新或插入的行,可以是表也可以是語句
則上面的需求我們可以利用MERGE簡單的實現:
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY
WHEN NOT MATCHED THEN
INSERT VALUES (T1.NAME,T1.MONEY);
COMMIT;
2. MERGE的完善
2.1. UPDATE 和 INSERT 動作可只出現其一
可選擇僅更新目標表:
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY;
COMMIT;
可選擇僅插入(INSERT)目標表而不做任何更新(UPDATE)操作:
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN NOT MATCHED THEN
INSERT VALUES (T1.NAME,T1.MONEY);
COMMIT;
2.2 可對MERGE語句加條件
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY
WHERE T1.NAME=’A’; — 此處表示對MERGE的條件進行過濾
COMMIT;
2.3 可用DELETE 子句清除行
清除行的前提條件是,要找到滿足 T1.NAME=T2.NAME 的記錄,如果T2.NAME=‘A’并不
滿足T1.NAME=T2.NAME過濾出的記錄集,那么 DELETE 是不會生效的,在滿足條件的
前提下,可以刪除目標表的記錄。
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY
DELETE WHERE (T2.NAME=’A’);
— DELETE WHERE (T2.NAME=’C’); 雖然 DELETE 語句不生效,但前面的 UPDATE 語句還是生效的
COMMIT;
2.4 可采用無條件方式 INSERT
在語法 ON 關鍵字處寫上恒不等條件(1=2)后,MATCHED 語句的 INSERT
就變為無條件 INSERT 了。
MERGE INTO T2
USING T1
ON (1=2)
WHEN NOT MATCHED THEN
INSERT VALUES (T1.NAME,T1.MONEY);
COMMIT;
3. MERGE 誤區探索
3.1 無法在源表中獲得一組穩定的行
在MERGE INTO T2 USING T1 ON … 的 MERGE 表達式中,如果一條T2記錄被連接到多條T1記錄,
就產生了ORA-30926錯誤
CREATE TABLE T1(NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T1 VALUES (‘A’,10);
INSERT INTO T1 VALUES (‘A’,30);
INSERT INTO T1 VALUES (‘B’,20);
COMMIT;
CREATE TABLE T2(NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T2 VALUES (‘A’,30); — T2.NAME 連接到多條 T1.NAME
INSERT INTO T2 VALUES (‘C’,20);
COMMIT;
此時繼續執行如下語句:
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY;
Oracle 中的 MERGE 語句應該保證 ON 條件的唯一性,T1.NAME=’A’時,T2表記錄
對應到了T1表的兩條記錄,所以就出錯了。
解決方法:
a. 對T1表和T2表的關聯字段建立主鍵,這樣就基本避免了此類問題,若MERGE語句
的關聯字段互相有主鍵,MERGE的效率將比較高;
b. 將T1表的NAME列做一個聚合,這樣歸并成單條,也能避免此類錯誤。
MERGE INTO T2
USING (SELECT NAME,SUM(MONEY) AS MONEY FROM T1 GROUP BY NAME) T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY;
但是這樣的改造需要注意,因為有可能改變了最初的需求,此外需要引起注意的是,
在MERGE INTO T2 USING T1 ON … 的 MERGE 表達式中,如果反過來,一條T1記
錄被連接到多條T2記錄,是可以使多條T2記錄都被更新而不會出錯。
DROP TABLE T1;
CREATE TABLE T1 (NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T1 VALUES (‘A’,10);
INSERT INTO T1 VALUES (‘B’,20);
DROP TABLE T2;
CREATE TABLE T2 (NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T2 VALUES (‘A’,30);
INSERT INTO T2 VALUES (‘A’,40);
INSERT INTO T2 VALUES (‘C’,20);
COMMIT;
此時繼續執行如下語句,發現執行可以成功并沒有報“無法再源表中獲得一組穩定的行”的錯誤
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY; — 此時T2表中NAME=’A’的兩條記錄都被更新了
3.2 DELETE 子句的 WHERE 順序必須在最后
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY
—WHERE T1.NAME=’A’
DELETE WHERE T2.NAME=’A’;
3.3 DELETE 子句只可以刪除目標表,而無法刪除源表
無論DELETE WHERE T2.NAME=’A’ 這個寫法的T2是否改寫為T1,效果都一樣,都是對目標表進行刪除
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY
DELETE WHERE T2.NAME=’A’; — DELETE WHERE T2.NAME=’A’ 刪除的還是目標表
總結
以上是生活随笔為你收集整理的MERGE 函数的使用[通俗易懂]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不得不知的做好电子商务运营的七部曲!点进
- 下一篇: linux下php的安装位置在哪