1. 程式人生 > >PLSQL 中Merge into和Update的用法

PLSQL 中Merge into和Update的用法

這兩天一直在處理關於SQL server儲存過程轉換到Oracle中,也發現一些oracle語句的區別。 

   在oracle 中有個語法:merge

   用法如下:

merge into 表1
  using 表2 或者(
select*from 表2)別名
  
on (表1.id=表2.id)
  
when matched thenupdateset 表1.列=表2.列

   還有無條件的insert語句:

MERGE INTO products p  USING newproducts np
  
ON (1=0)  WHENNOT MATCHED THENINSERTVALUES
 (np.product_id, np.product_name, np.category)
  
WHERE np.category ='BOOKS'

   update的寫法:    

    今天改寫一個T_sql語句到PL/SQL中,原句是通過兩個表關聯查詢取出資料,然後更新,在oracle中是不支援這樣的寫法的。一開始通過不加條件直接寫,發現全部語句被更新了。後來在where語句下增加id的限制條件。

update formfield s set typeid=nvl((select doctypeid from pipedoctype f where s.id=f.fieldid 
and rownum=1),'')where s.id in (select fieldid from pipedoctype);
commit;

   總結:   

     update語句區別:就是在更新的時候,其更新語句資料來源是從另一個關聯表中取出時,使用上述方法;


merge into 是特有的功能,相當於在 MSSQL中的

if exists(...)

   update table

else

   Insert into table.

merge into 語法不僅沒有if exists語法囉嗦,而且比if exists 還要高效很多。我經常用來在oracle之間同步資料庫表。

語法如下:

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);

1、

從語法條件上看( ON (join condition) ),merge into也是一個危險的語法。如果不慎重使用,會將alias2 表全部覆蓋alias1,既危險又浪費效率,違背了增量同步的原則。我在設計表結構中,一般每條記錄都有“更新時間”的欄位,用alias1“最大更新時間”判斷alias2 資料是否有更新和新增的資訊。須謹慎控制alias2 條件。

2、更新的欄位,不允許有關聯條件的欄位(join condition)。比如條件是 A.ID=B.ID,那麼使用“SET A.ID=B.ID”將報出一個莫名其妙的提示錯誤。

該命令使用一條語句從一個或者多個數據源中完成對錶的更新和插入資料. ORACLE 9i 中,使用此命令必須同時指定UPDATE 和INSERT 關鍵詞,ORACLE 10g 做了如下改動。

1,insert 和update是可選的 2,UPDATE 和INSERT 後面可以跟WHERE 子句 3,在ON條件中可以使用常量來insert 所有的行到目標表中,不需要連線到源表和目標表 4,UPDATE 子句後面可以跟delete 來去除一些不需要的行。

舉例:

  1. createtable PRODUCTS   
  2.     (   
  3.     PRODUCT_ID INTEGER,   
  4.     PRODUCT_NAME VARCHAR2(60),   
  5.     CATEGORY VARCHAR2(60)   
  6.     );   
  7. insertinto PRODUCTS values (1501, 'VIVITAR 35MM''ELECTRNCS');   
  8. insertinto PRODUCTS values (1502, 'OLYMPUS IS50''ELECTRNCS');   
  9. insertinto PRODUCTS values (1600, 'PLAY GYM''TOYS');   
  10. insertinto PRODUCTS values (1601, 'LAMAZE''TOYS');   
  11. insertinto PRODUCTS values (1666, 'HARRY POTTER''DVD');   
  12. commit;   
  13. createtable NEWPRODUCTS   
  14.     (   
  15.     PRODUCT_ID INTEGER,   
  16.     PRODUCT_NAME VARCHAR2(60),   
  17.     CATEGORY VARCHAR2(60)   
  18.     );   
  19. insertinto NEWPRODUCTS values (1502, 'OLYMPUS CAMERA''ELECTRNCS');   
  20. insertinto NEWPRODUCTS values (1601, 'LAMAZE''TOYS');   
  21. insertinto NEWPRODUCTS values (1666, 'HARRY POTTER''TOYS');   
  22. insertinto NEWPRODUCTS values (1700, 'WAIT INTERFACE''BOOKS');   
  23. commit;   
  24. 1,可省略的update 或者insert
  25.    MERGE INTO products p   
  26.     2 USING newproducts np   
  27.     3 ON (p.product_id = np.product_id)   
  28.     4 WHEN MATCHED THEN
  29.     5 UPDATE
  30.     6 SET p.product_name = np.product_name,   
  31.     7 p.category = np.category;

  使用表newproducts中的product_name 和category欄位來更新表products 中相同product_id的product_name 和category.

2,當條件不滿足的時候把newproducts表中的資料INSERT 到表products中。

  1. MERGE INTO products p   
  2.     USING newproducts np   
  3. ON (p.product_id = np.product_id)   
  4. WHENNOT MATCHED THEN
  5. INSERT
  6. VALUES (np.product_id, np.product_name,   
  7.      np.category);   

3,帶條件的insert 和update

  1. 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;

 insert 和update 都帶有where 字句

  1. 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. WHENNOT MATCHED THEN
  10. INSERT
  11. VALUES (np.product_id, np.product_name, np.category)   
  12. WHERE np.category != 'BOOKS'  

4,無條件的insert

  1. MERGE INTO products p   
  2.  USING newproducts np   
  3. ON (1=0)   
  4. WHENNOT MATCHED THEN
  5. INSERT
  6. VALUES (np.product_id, np.product_name, np.category)   
  7. WHERE np.category = 'BOOKS'

5,delete 子句

1  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  delete where category = 'macle1_cate';

select *

from products;

 PRODUCT_ID PRODUCT_NAME         CATEGORY
--------------------------------------- -------------------- --------------------
                                   1502 macle22              macle2_cate
                                   1503 macle3                macle2_cate
                                   1504 macle                  macle1_cate
                                   1505 macle5                macle5_cate

1504 中的macle1_cate 滿足delete where,但是不滿足 on 中的條件,所以沒有被刪除。!!!!!!重點

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

動機:

想在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 
WHENNOT 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
  
UPDATESET T1.b =2
WHENNOT 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,2AS b FROM dual) T2
ON ( T1.a=T2.a)
WHEN MATCHED THEN
  
UPDATESET T1.b = T2.b
WHENNOT MATCHED THEN 
  
INSERT (a,b) VALUES(T2.a,T2.b);

查詢結果,OK!

注意:

如果不懂Merge語句的原理,Merge語句是一條比較危險的語句,特別是在您只想更新一條記錄的時候,因為不經意間,你可能就把整表的資料都Update了一遍.....汗!!!

我曾經犯過的一個錯誤如下所示,大家看出來是什麼問題了嗎?

MERGE INTO T T1
USING (
SELECTCount(*) cnt FROM T WHERE T.a='1001') T2
ON (T2.cnt>0)
WHEN MATCHED THEN
  
UPDATESET T1.b = T2.b
WHENNOT MATCHED THEN 
  
INSERT (a,b) VALUES(T2.a,T2.b);

相關推薦

PLSQL Merge intoUpdate用法

這兩天一直在處理關於SQL server儲存過程轉換到Oracle中,也發現一些oracle語句的區別。     在oracle 中有個語法:merge    用法如下: merge into 表1   using 表2 或者(select*from 表2)別名

OracleMerge into用法總結 (轉載)

字符 存在 sin 刪除 ron mic 但是 多個 前段時間 Oracle中Merge into用法總結 (出處:http://www.cnblogs.com/dongsheng/p/4384754.html) 起因:   前段時間,因為涉及到一張表的大數據操作,要同時

oracle merge into用法

大數據 char 條件 http -1 alt mat 一個表 dml語句 很多時候我們需要通過篩選條件同時對表進行 更新,插入,刪除 等操作。這樣如果我們單一的去操作表會顯得很麻煩,下面會說到這個merge into 的用法會極大的優化我們操作表的時間和代碼量。 舉例,

oraclemerge into用法

merge into的形式: [sql]  view plain  copy MERG

ORACLE merge....into用法簡單瞭解一下

MERGE INTO [target-table] A USING [source-table sql] B ON([conditional expression] and […]…) WHEN MATCHED THEN [UPDATE sql] WHEN NO

oraclemerge into用法解析

merge into的形式: MERGE INTO [target-table] A USING [source-table sql] B ON([conditional expression] and [...]...) WHEN MATCHED THEN [UPDAT

oraclemerge into..using..on..when..when..用法

語法:MERGE INTO [your table-name] [rename your table here] USING ( [write your query here] )[rename your query-sql and using just like a ta

腳本引用使用deferasync用法區別

兩個 不依賴 doc 體驗 html 中文 htm 停止 其他 是的,就是在頁面腳本引用的時候設置defer或者async,為什麽會有這兩個屬相來輔助腳本加載那,因為瀏覽器在遇到script標簽的時候,文檔的解析會停止,不再構建document,有時打開一個網頁上會出現空

Objective-C的@property@synthesize用法

有時 頭文件 關鍵字 nbsp nsa atomic 所有者 ica 風險 描述 @代表“Objective-C”的標誌,證明您正在使用Objective-C語言。 是Objective-C語言關鍵詞。 @property與@synthesize配對使用。 功能:讓編譯

oraclemerge into的使用

rollback 裏的 get express pre sql語句 可選 需求 目標 Oracle在9i引入了merge命令, 通過這個merge你能夠在一個SQL語句中對一個表同時執行inserts和updates操作. 當然是update還是insert是依據於你的指定

python的andor用法

在python中and和or返回的值並不是True和false這麼簡單。雖然他們看上去和c++中的&&和||有些相似。在瞭解and和or之前,我們先要了解python中的True和False。 在python裡面,0、’’、[]、()、{}、None為假,其它任何東西都為真。ok,在此前提下

JS的callapply用法

//基本用法 var a = [1, 2]; function cut(a, b) { console.log(a - b) }; cut.apply(a, [a[0], a[1]]); //-1 cut.call(a, a[0], a[1]) //-1 //實現繼承 fu

pandas.DataFrame()的ilocloc用法

簡單的說: iloc,即index locate 用index索引進行定位,所以引數是整型,如:df.iloc[10:20, 3:5] loc,則可以使用column名和index名進行定位,如: df.loc[‘image1’:‘image10’, ‘age’:‘score’] 例項:

Oracle之with asupdate用法

許久不用,又忘了,做個記錄 update test b set b.code=(with t as(select t.id,code||'_'||row_number() over(partition by code order by id) codefrom test t)select a.code fr

oracle的CURRVALNEXTVAL用法

1.什麼是sequence?其作用是什麼? 在Oracle資料庫中,什麼是序列呢?其中的作用是什麼呢?其實sequence是序列號生成器,可以為表中的行自動生成序列號,產生一組等間隔的數值(型別為數字)。其主要的用途是生成表的主鍵值,可以在插入語句中引用,在插入

C#HashTable簡介使用用法

一、簡介 名詞介紹:散列表(Hash table,也叫雜湊表),是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做散列表。 HashTable

mybatismerge into批量使用問題

insert 和update中所有的資料都需要從using中獲取,這樣就能達到批量merge into的效果了 MERGE INTO TM_USER_CART_INFO T1 USING  ( <foreach collection="list" item="item

java隨機數RandomThreadLocalRandom()用法與區別

package com.test; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; public class M1001{ public static v

Oracle的select for update 用法

通常情況下,select語句是不會對資料加鎖,不會妨礙影響其他的DML和DDL操作。藉助for update子句,我們可以在應用程式的層面手工實現資料加鎖保護操作。當只允許一個session進行update的時候, for update十分有用. 在select…for update之後,可以使

Python的lambdaapply用法

目錄 2.1 舉例 3 參考文獻 1 lambda lambda原型為:lambda 引數:操作(引數) lambda函式也叫匿名函式,即沒有具體名稱的函式,它允許快速定義單行函式,可以用在任何需要函式的地方。這區別於def定義的函式。 lam