Sql-Server
MERGE 最佳實踐的說明
我只是想從“優化 MERGE 語句性能”頁面詢問有關 MSDN 上的某些內容的澄清。
我正在使用一個數據倉庫,它從許多不同的數據庫中獲取記錄並儲存數據。我的倉庫數據庫中的所有表基本上都遵循相同的模式:
CREATE TABLE Foo ( database_guid UNIQUEIDENTIFIER ,FooPk BIGINT ,Bar NVARCHAR(20) ,Qix NCHAR(10) ,CONSTRAINT [PK_Foo] PRIMARY KEY CLUSTERED ( database_guid ASC ,FooPk ASC ) ) GO CREATE PROCEDURE [iv].[LoadSomeTable] @databaseGUID UNIQUEIDENTIFIER AS BEGIN SET NOCOUNT ON MERGE Foo USING #FooStaging AS Source ON Foo.FooPk = Source.FooPk AND Foo.database_guid = @databaseGUID WHEN MATCHED THEN UPDATE SET Bar = Source.Bar ,Qix = Source.Qix WHEN NOT MATCHED THEN INSERT (database_guid, FooPk, Bar, Qix) VALUES (@databaseGUID, FooPk, Bar, Qix); END GO CREATE TABLE #FooStaging ( FooPk BIGINT ,Bar NVARCHAR(20) ,Qix NCHAR(10) ) --Data gets loaded in to #FooStaging from a C# call to SqlBulkCopy then calls iv.LoadSomeTable
我現在擔心的是我剛剛從那個 MSDN 頁面上讀到了這個聲明
僅在 ON
<merge_search_condition>
子句中指定用於確定源表和目標表中的數據匹配條件的搜尋條件。也就是說,僅指定目標表中與源表的對應列進行比較的列。不要包括與其他值(例如常數)的比較。讀完之後,我認為我的查詢錯誤,我的合併語句應該是
MERGE Foo USING #FooStaging AS Source ON Foo.FooPk = Source.FooPk WHEN MATCHED AND Foo.database_guid = @databaseGUID THEN UPDATE SET Bar = Source.Bar ,Qix = Source.Qix WHEN NOT MATCHED THEN INSERT (database_guid, FooPk, Bar, Qix) VALUES (@databaseGUID, FooPk, Bar, Qix);
但這對我來說“感覺”不正確,因為該
database_guid
欄位是主鍵的一部分,所以它不應該包含在on
? 如果我有它,然後我WHEN MATCHED
用 a 上傳一個數據庫FooPk
,1
然後我用 aFooPk
和另一個不同的數據庫上傳第二個數據庫,@databaseGUID
我不確定是否NOT MATCHED
會觸發(剛剛測試過,它不會)。哪種方式是使用 MERGE 的正確方式?
我敢說,您最好的方法是對每個潛在操作使用單獨的語句,並將它們放入可序列化的事務中。你可以使用經過驗證的真實陳述,沒有有趣的語義或“最佳實踐”違規,你可以避免我在這篇文章中概述的所有問題,包括錯誤的結果錯誤和潛在的索引損壞: