Soru SQL MERGE deyiminde UPDATE-no-op


İçinde bazı kalıcı veriler bulunan bir tablom var. Şimdi sorguladığımda, sonuç için gereken değerleri hesaplayan oldukça karmaşık bir CTE'ye sahibim ve kalıcı tabloyu kalıcı tabloya eklemem gerekiyor. Sonunda, CTE tarafından belirlenen tüm satırlardan oluşan sonucu seçmek istiyorum, ancak tablodaki veriler tablodaysa ve bir satırın yeni eklenip eklenmediğine dair bilgiye ihtiyacım var.

Basitleştirilmiş bu şekilde çalışır (denemek isterseniz aşağıdaki kod normal sorgu olarak çalışır):

-- Set-up of test data, this would be the persisted table 
DECLARE @target TABLE (id int NOT NULL PRIMARY KEY) ;
INSERT INTO @target (id) SELECT v.id FROM (VALUES (1), (2)) v(id);

-- START OF THE CODE IN QUESTION
-- The result table variable (will be several columns in the end)
DECLARE @result TABLE (id int NOT NULL, new bit NOT NULL) ;

WITH Source AS (
    -- Imagine a fairly expensive, recursive CTE here
    SELECT * FROM (VALUES (1), (3)) AS Source (id)
)
MERGE INTO @target AS Target
    USING Source
    ON Target.id = Source.id
    -- Perform a no-op on the match to get the output record
    WHEN MATCHED THEN 
        UPDATE SET Target.id=Target.id
    WHEN NOT MATCHED BY TARGET THEN
        INSERT (id) VALUES (SOURCE.id)
    -- select the data to be returned - will be more columns
    OUTPUT source.id, CASE WHEN $action='INSERT' THEN CONVERT(bit, 1) ELSE CONVERT(bit, 0) END
      INTO @result ;

-- Select the result
SELECT * FROM @result;

Ben sevmiyorum WHEN MATCHED THEN UPDATE Kısmı, gereksiz güncellemeyi uzak bırakmayı tercih ediyorum ancak sonuç satırında OUTPUT fıkra.

Bu, bu tür bir veriyi tamamlayıp iade etmek için en etkili yol mu?

Ya da olmadan daha verimli bir çözüm olurdu MERGEörneğin, sonucu bir bilgisayarla önceden hesaplayarak SELECT ve sonra bir INSERT satırların new=0? Temelde "Kümelenmiş Dizini Birleştirme" ye kaydığı için sorgu planını yorumlamakta zorluk çekiyorum ki bu da bana göre performans açısından oldukça belirsiz. SELECT bunu takiben INSERT varyant. Ve merak ediyorum ki SQL Server (CU1 ile 2008 R2) aslında bunu görmek için yeterince akıllı UPDATE bir no-op'dur (ör., yazma gerektirmez).


18
2018-03-15 19:05


Menşei


Benimle birleştirme, birleştirme ve bir yedekli güncelleştirme ile tam olarak aynı ayarlara sahibim ve ayrıca bir güncelleştirme gerçekleştirmeyen ancak yine de kimliği döndüren bir çözüm arıyorum. Bir çözüm bulursanız lütfen ekleyin =) - David Mårtensson
RE: Güncellenmeyen Güncelleme Güncellemesi, muhtemelen burada açıklandığı gibi kümeleme anahtarının bir parçası olmayan bir sütun üzerinde No-OP güncellemesi yapmaktan daha iyi olacaktır. sqlblog.com/blogs/paul_white/archive/2010/08/11/... - Martin Smith
@David Mårtensson, lütuf eklediğiniz için teşekkürler. :) - Lucero
@Lucero - Seni takip edersem göreyim. Bir tutam satırı @target’e eklemek ve @result’a eklenen satırları çıkarmak istiyorsunuz. Bu doğru mu? - Thomas
Eğer bunu anlarsam, hem girilen kimlikleri hem de varolan satırların kimliğini, birleşmenin geldiği şeyi ister. Birleşme olmadan, zaten varolan diğer satırların kimliklerini alamazsınız. Sorunun amacı, gerçek performans olmadan maliyet performansı olarak yapılabilir. - David Mårtensson


Cevaplar:


Bir kukla değişkeni bildirebilir ve değerinizi NEEN MATCHED yan tümcesinde belirtebilirsiniz.

 DECLARE @dummy int;
 ...
 MERGE
 ...
 WHEN MATCHED THEN
   UPDATE SET @dummy = 0
 ...

Gerçek tablo güncellemesinden daha ucuz olması gerektiğine inanıyorum.


25
2018-05-04 14:10



Bu harika bir fikir ve iyi çalışıyor gibi görünüyor. Birisi daha da iyi bir şey ortaya çıkarsa, bunu cevap olarak kabul edeceğim ... MERGE. - Lucero
Bu çözüm benim problemimi en azından 100 rep ödülüne layık buldu =) Teşekkürler Andriy ve Lucero, cevabı ve örnekle ilgili iyi bir soru için. - David Mårtensson
@David, teşekkürler! Bu gerçekten iyi bir soru. Bunun gibi şeyler, gerekli bilgiye ihtiyaç duyan gerçek bir problem olana kadar beklemek yerine, genellikle önceden bilmeye değerdir. - Andriy M