使用MERGE語句同步表,merge語句同步
先建好測試環境: USE TEMPDBGOIF OBJECT_ID('T1') IS NOT NULL DROP TABLE T1IF OBJECT_ID('T2') IS NOT NULL DROP TABLE T2GOCREATE TABLE T1(ID1 INT,VAL1 VARCHAR(50))CREATE TABLE T2(ID2 INT,VAL2 VARCHAR(50))GOINSERT INTO T1SELECT 1,'A' UNION ALLSELECT 2,'B' UNION ALLSELECT 3,'C' 現在我們的目標是讓T2表與T1表同步,我直接把完整的MERGE語句帖上來,等下再細說各個部分:
MERGE INTO T2 AS TB_TARGETUSING T1 AS TB_SOURCEON TB_TARGET.ID2=TB_SOURCE.ID1WHEN NOT MATCHED BY TARGET THEN INSERT(ID2,VAL2)VALUES(ID1,VAL1)WHEN NOT MATCHED BY SOURCE THENDELETEWHEN MATCHED AND TB_TARGET.VAL2<>TB_SOURCE.VAL1 THEN UPDATE SETTB_TARGET.VAL2=TB_SOURCE.VAL1OUTPUT $ACTION,ISNULL(DELETED.ID2,INSERTED.ID2) AS ID,DELETED.VAL2,INSERTED.VAL2;看看MERGE語句輸出的結果/*$ACTION ID2 VAL2 VAL2---------- ----------- -------------------------------------------------- --------------------------------------------------INSERT 1 NULL AINSERT 2 NULL BINSERT 3 NULL C*/再看一下現在T2的內容: SELECT * FROM T2/*ID2 VAL2----------- --------------------------------------------------1 A2 B3 C*/ 可以看到T1的東東已經過去了,也就是說初步的同步完成了。現在做一些其它的操作,我們分別插入、更新、刪除一條資料:UPDATE T1 SET VAL1='D' WHERE ID1=3DELETE FROM T1 WHERE ID1=2INSERT INTO T1SELECT 4,'E'SELECT * FROM T1 /*ID1 VAL1----------- --------------------------------------------------1 A4 E3 D*/現在各種資料都有了,1沒變,2刪了,3改了,4是加的。再運行上面那坨MERGE語句:MERGE INTO T2 AS TB_TARGETUSING T1 AS TB_SOURCEON TB_TARGET.ID2=TB_SOURCE.ID1WHEN NOT MATCHED BY TARGET THEN INSERT(ID2,VAL2)VALUES(ID1,VAL1)WHEN NOT MATCHED BY SOURCE THENDELETEWHEN MATCHED AND TB_TARGET.VAL2<>TB_SOURCE.VAL1 THEN UPDATE SETTB_TARGET.VAL2=TB_SOURCE.VAL1OUTPUT $ACTION,ISNULL(DELETED.ID2,INSERTED.ID2) AS ID,DELETED.VAL2,INSERTED.VAL2;/*$ACTION ID VAL2 VAL2---------- ----------- -------------------------------------------------- --------------------------------------------------INSERT 4 NULL EDELETE 2 B NULLUPDATE 3 C D*/ 看一下T2的資料SELECT * FROM T2/*ID2 VAL2----------- --------------------------------------------------1 A3 D4 E*/可以看到,資料已經完全同步了。看到效果後,我們就可以開始說本文了,我再粘一次MERGE語句,然後一句一句細說MERGE INTO T2 AS TB_TARGETUSING T1 AS TB_SOURCEON TB_TARGET.ID2=TB_SOURCE.ID1WHEN NOT MATCHED BY TARGET THEN INSERT(ID2,VAL2)VALUES(ID1,VAL1)WHEN NOT MATCHED BY SOURCE THENDELETEWHEN MATCHED AND TB_TARGET.VAL2<>TB_SOURCE.VAL1 THEN UPDATE SETTB_TARGET.VAL2=TB_SOURCE.VAL1OUTPUT $ACTION,ISNULL(DELETED.ID2,INSERTED.ID2) AS ID,DELETED.VAL2,INSERTED.VAL2; 1.MERGE INTO T2 AS TB_TARGET指定要同步的目標表。MERGE是關鍵字,INTO可有可無,T2是目標表名,AS可有可無,TB_TARGET是表別名。如果要對目標表加表提示和索引提示,比如WITH(...),加在T2和AS中間就可以了。2.USING T1 AS TB_SOURCE指定用來作為同步源的表或其它東東。USING是關鍵字,T1是原表名或一個子查詢,比如一堆JOIN出來的東西用括弧括起來。AS同上,TB_SOURCE是別名。3.ON TB_TARGET.ID2=TB_SOURCE.ID1關聯條件,沒什麼好說的,注意這裡開始就用到上面定義的別名了。4.WHEN NOT MATCHED BY TARGET THENINSERT(ID2,VAL2)VALUES(ID1,VAL1)這裡放到一起說。看到INSERT應該就能猜這段語句的意思是“如果原表有的記錄新表沒有,就插入”。NOT MATCHED表示不匹配, BY TARGET表示是新表找不到匹配原表條件(就是上面的ON後寫的)的記錄, BY TARGET 可以不寫,預設就是BY TARGET,但如果要寫兩個WHEN MATCHED就必須要寫,比如上面這個MERGE。第二三行和普通的插入語句差不多,區別就在於沒有目標表名和只能用VALUES不能用SELECT,因為這裡都是針對單行的操作。5.WHEN NOT MATCHED BY SOURCE THENDELETE這個就簡單了,如果是原表找不到新表的匹配記錄,就把新表的刪了。需要注意的就是如果要加上這句,上面的NOT MATCHED必須加BY TARGET。6.WHEN MATCHED AND TB_TARGET.VAL2<>TB_SOURCE.VAL1 THEN UPDATE SETTB_TARGET.VAL2=TB_SOURCE.VAL1第一行後面的AND部分可以不要,相當於更新的另一個匹配條件,像上面例子中,ID為1的那條資料沒有動,但因為能找到匹配記錄還是會更新,加上條件就可以避免這種無效操作了。7.OUTPUT $ACTION,ISNULL(DELETED.ID2,INSERTED.ID2) AS ID,DELETED.VAL2,INSERTED.VAL2這行可以都去掉,作用就是輸出同步的資料,用過觸發器的同學對INSERTED和DELETED兩個表應該灰常熟悉,分別放的是更新後的值和更新前的值,看看最後一次MERGE輸出的資訊就能差不多看出門道了,我就不多說了。如果要調試語句的話,可以加上這句,正常的同步就可以去掉了。8.;這個必須有。。。。。 總之,4,5,6,7都是可以去掉的,但4,5,6至少要有一個,這就是MERGE的全部常用文法了。還有一個最後可以加 OPTION查詢提示 最後簡單對比一下MERGE和原本同樣效果的操作的IO對比MERGE INTO T2 AS TB_TARGETUSING T1 AS TB_SOURCEON TB_TARGET.ID2=TB_SOURCE.ID1WHEN NOT MATCHED BY TARGET THEN INSERT(ID2,VAL2)VALUES(ID1,VAL1)WHEN NOT MATCHED BY SOURCE THENDELETEWHEN MATCHED AND TB_TARGET.VAL2<>TB_SOURCE.VAL1 THEN UPDATE SETTB_TARGET.VAL2=TB_SOURCE.VAL1OUTPUT $ACTION,ISNULL(DELETED.ID2,INSERTED.ID2) AS ID,DELETED.VAL2,INSERTED.VAL2; /*表 'T2'。掃描計數 2,邏輯讀取 7 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。表 'T1'。掃描計數 2,邏輯讀取 4 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。*/ PRINT '------------------------------------------------------------------------------------'INSERT INTO T2(ID2,VAL2)SELECT ID1,VAL1FROM T1 WHERE NOT EXISTS(SELECT 1 FROM T2 WHERE T2.ID2=T1.ID1)UPDATE T2SET T2.VAL2=T1.VAL1FROM T2INNER JOIN T1 ON T2.ID2=T1.ID1AND T2.VAL2<>T1.VAL1DELETE FROM T2 WHERE NOT EXISTS(SELECT 1 FROM T1 WHERE T1.ID1=T2.ID2) /*表 'T2'。掃描計數 1,邏輯讀取 4 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。表 'Worktable'。掃描計數 1,邏輯讀取 5 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。表 'T1'。掃描計數 1,邏輯讀取 1 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。表 'T2'。掃描計數 1,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。表 'T1'。掃描計數 1,邏輯讀取 4 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。表 'T2'。掃描計數 1,邏輯讀取 1 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。表 'T1'。掃描計數 1,邏輯讀取 4 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。*/
SQL Server2008中的MERGE SQL語句中的MERGE的全稱是什麼?代表什麼意思? 有沒有
merge 是sqlserver2008的新語句
SQL Server 2008將包含用於合并兩個行集(rowset)資料的新句法。根據一個來源資料表對另一個資料表進行確定性插入、更新和刪除這樣複雜的操作,運用新的MERGE語句,開發人員用一條命令就可以完成。
對兩個表進行資訊同步時,有三步操作要進行。首先要處理任何需要插入目標資料表的新行。其次是處理需要更新的已存在的行。最後要刪除不再使用的舊行。這個過程中需要維護大量重複的邏輯,並可能導致微妙的錯誤。
Bob Beauchemin討論了MERGE語句,這個語句將上述的多個操作步驟合并成單一語句。他給出了如下的例子:
merge [target] t
using [source] s on t.id = s.id
when matched then update set t.name = s.name, t.age = s.age -- use "rowset1"
when not matched then insert values(id,name,age) -- use "rowset2"
when not matched by source then delete; -- use "rowset3"
如你所見,具體操作是根據後面的聯合(join)的解析結果來確定的。在這個例子中,如果目標和來源資料表有匹配的行,就實行更新操作。如果沒有,就實行插入或者刪除操作來使目標資料表和來源資料表保持一致。
這個新句法的一個美妙之處是它在處理更新時的確定性。在使用標準的UPDATE句法和聯合時,可能有超過一個源行跟目標行匹配。在這種情況下,無法預料更新操作會採用哪個源行的資料。
而當使用MERGE句法時,如果存在多處匹配,它會拋出一個錯誤。這就提醒了開發人員,要達到預想的目標,當前的聯合條件還不夠明確。
至於 ppt 沒有
有本pdf ishare.iask.sina.com.cn/f/16236919.html
使用merge語句遇到的問題
這是什麼錯誤啊?