2009-08-12 3 views
26

Mi chiedo cosa si consiglia di considerare come il modo migliore per ottenere il conteggio delle azioni da un'istruzione MERGE in Sql Server.Sql Server 2008 MERGE - il modo migliore per ottenere i conteggi

Quindi, io eseguo un MERGE che fa alcuni inserimenti, alcuni aggiornamenti e alcune eliminazioni, ... Mi piacerebbe essere in grado di scoprire QUANTI inserti, QUANTI aggiornamenti e quante cancellazioni.

Qual è il modo migliore per farlo?

risposta

31

È possibile specificare una clausola OUTPUT sull'istruzione MERGE e ottenere un rapporto di output su cosa è stato fatto durante MERGE.

MERGE (targetTable) AS t 
USING (sourceTable) AS s 
ON t.ID = s.ID 
WHEN MATCHED THEN 
    (some statements) 
WHEN NOT MATCHED THEN 
    (some statements) 
OUTPUT 
    $action, inserted.ID 'inserted', deleted.ID 'deleted' 
; 

Questo ti darà una riga per ogni "azione" (inserisci, aggiorna, cancella) per ogni operazione. Se ci sono molte dichiarazioni, potresti anche USCITE IN @tableVar e poi guarda la variabile di tabella.

DECLARE @tableVar TABLE (MergeAction VARCHAR(20), InsertedID INT, DeletedID INT) 

MERGE (targetTable) AS t 
USING (sourceTable) AS s 
ON t.ID = s.ID 
WHEN MATCHED THEN 
     (some statements) 
WHEN NOT MATCHED THEN 
     (some statements) 
OUTPUT 
     $action, inserted.ID 'inserted', deleted.ID 'deleted' INTO @tableVar 
; 

SELECT MergeAction, COUNT(*) 
FROM @tableVar 
GROUP BY MergeAction 

Partenza documentazione in linea per i dettagli sulla MERGE dichiarazione e la OUTPUT clause.

Marc

+0

È possibile farlo in qualche modo in una dichiarazione, possibilmente con un gruppo? in modo che il bit di output sia qualcosa di simile a> OUTPUT $ ACTION, COUNT (1) GROUP BY $ ACTION? – eidylon

+0

No, non puoi farlo. È possibile utilizzare solo OUTPUT nella finestra di output SSMS o in una variabile di tabella - non allungare eccessivamente la clausola OUTPUT !! :-) –

+0

Ah bene ... In realtà, OUTPUT ha messo fuori una variabile di tabella o un set di risultati? Sarebbe possibile racchiudere l'istruzione MERGE con una clausola OUTPUT all'interno di un'istruzione SELECT come origine (come sottoquery) e quindi avere SELECT esterno che fa l'aggregazione? ... Sembra possibile. Potrei dover giocare con quello. – eidylon

1

ne dite:

INSERT YourResultsTable (action, cnt) 
SELECT action, count(*) 
FROM 
(
    MERGE (targetTable) AS t 
    USING (sourceTable) AS s 
     ON t.ID = s.ID 
    WHEN MATCHED THEN  (some statements) 
    WHEN NOT MATCHED THEN  (some statements) 
    OUTPUT $action as action, inserted.ID as ins, deleted.ID as del 
) m 
GROUP BY action; 

[Edit] Ok, in modo da provare:

INSERT YourResultsTable (action) 
SELECT action 
FROM 
(
    MERGE (targetTable) AS t 
    USING (sourceTable) AS s 
     ON t.ID = s.ID 
    WHEN MATCHED THEN  (some statements) 
    WHEN NOT MATCHED THEN  (some statements) 
    OUTPUT $action as action, inserted.ID as ins, deleted.ID as del 
) m; 

(e poi contare i risultati)

Rob

+0

No: messaggio 10717, livello 15, stato 1, riga 48 La clausola GROUP BY non è consentita quando la clausola FROM contiene un INSERT nidificato , UPDATE, DELETE o MERGE. –

+0

Testato su SQL Server 2008 Developer Edition –

+0

Ho utilizzato la modifica, quindi ho preso la tabella inserita e aggregato le singole azioni in totali SOMMA utilizzando le dichiarazioni case e registrato tali risultati. Funziona alla grande! Puzza che SQL Server mi imponga di inserire i risultati di unione in una variabile di tabella invece di aggregare e impostare le mie variabili int direttamente nella selezione più esterna. – MikeTeeVee

4

Per estrarre in indiv vars idual, possono inviare risposta processo marc_s utilizzando pivot:

declare 
     @mergeResultsTable table (MergeAction VARCHAR(20)); 

    declare 
     @insertCount int, 
     @updateCount int, 
     @deleteCount int; 

    merge ... 
    output $action into @mergeResultsTable; 

    select @insertCount = [INSERT], 
      @updateCount = [UPDATE], 
      @deleteCount = [DELETE] 
     from (select 'NOOP' MergeAction -- row for null merge into null 
      union all 
      select * from @mergeResultsTable) mergeResultsPlusEmptyRow  
    pivot (count(MergeAction) 
     for MergeAction in ([INSERT],[UPDATE],[DELETE])) 
     as mergeResultsPivot; 

L'unione 'noop' riga può essere rimossa se init VAR di 0 o sapere che sorgente o destinazione tabella ha> 0 righe.