2017-08-08 2 views
0

j'ai besoin d'insérer des lignes de sélection, si la clé est un doublon puis supprimez l'entrée et insérez-lesErreur clé en double dans SQL et supprimer et mettre à jour

Table1 

    ColumnA ColumnB ColumnC ColumnD 
    A   1  A1  7/21/2017 
    B   2  B1  7/22/2017 
    C   3  C1  7/23/2017 

Combinaison unique ColumnA et ColumnC

Table2 

    ColumnE ColumnF ColumnG 
    A  1  A1 
    A   2  A2 
    B   3  B1 
    B   2  B2 
    C   3  C1 
    C   1  C2 

I devrait insérer les lignes du tableau 2 au tableau 1

Insert into table1 (columnA, columnB, ColumnC) select columnE, ColumnF, ColumnG from table2 

La requête ci-dessus obtient des conflits disant du Les clés pliées sont insérées mais veulent un moyen de supprimer des lignes qui crée des conflits et insérer cette ligne. sortie finale devrait être

Table 1 
ColumnA ColumnB ColumnC ColumnD 
    A  1  A1  08/08/2017 - deleted and added as conflict arised 
    A   2  A2  08/08/2017 
    B   3  B1  08/08/2017 -deleted and added as conflict arised 
    B   2  B2  08/08/2017 
    C   3  C1  08/08/2017  
    C   1  C2  08/08/2017 
+1

'MERGE'. 'QUAND CORRESPONDU, PUIS MISE À JOUR'. –

+0

Pouvez-vous s'il vous plaît fournir un exemple spécifique pour ce cas? – TechJump

+1

La fusion est encore malheureusement lente. une séquence DI (Delete, puis Insert) sera probablement meilleure, bien qu'une séquence UI (update, then insert) soit la meilleure. –

Répondre

0

Vous ne devez pas supprimer puis insérer. Il suffit de mettre à jour la colonne ColumnD (ou toutes les colonnes sans clé) et d'en insérer de nouvelles à partir du Table2. Je voudrais commander des déclarations de sorte que d'abord va UPDATE puis INSERT, de sorte que le UPDATE fonctionne sur un plus petit ensemble de lignes d'origine (avant l'insertion). Ici, il est, au lieu de MERGE, tout simplement vieux UPDATE-INSERT:

DECLARE 
    @Conflicted TABLE(
     ColumnA char(1), 
     ColumnB int, 
     ColumnC char(2), 
     ColumnD date 
    ) 

BEGIN TRAN 

UPDATE dst 
SET 
    dst.ColumnD = GETDATE() 
OUTPUT 
    deleted.ColumnA, 
    deleted.ColumnB, 
    deleted.ColumnC, 
    deleted.ColumnD 
INTO 
    @Conflicted 
FROM 
    Table1 AS dst 
    JOIN Table2 AS src 
    ON dst.ColumnA = src.ColumnE AND 
     dst.ColumnB = src.ColumnF AND 
     dst.ColumnC = src.ColumnG 

INSERT INTO Table1(
    ColumnA, 
    ColumnB, 
    ColumnC, 
    ColumnD 
) 
SELECT 
    t2.ColumnE, 
    t2.ColumnF, 
    t2.ColumnG, 
    GETDATE() 
FROM 
    Table2 AS t2 
WHERE 
    NOT EXISTS(SELECT * FROM Table1 WHERE ColumnA = t2.ColumnE AND ColumnB = t2.ColumnF AND ColumnC = t2.ColumnG) 

COMMIT TRAN 

Dans la table des variables @Conflicted maintenant vous avez toutes les lignes en conflit de la Table1 qui ont été remplacées par de nouvelles du Table2.

Et voici une version avec MERGE:

DECLARE 
    @Updated TABLE(
     ColumnA char(1), 
     ColumnB int, 
     ColumnC char(2), 
     ColumnD date, 
     Action nvarchar(10) 
    ) 

MERGE Table1 AS dst 
USING (
    SELECT * FROM Table2 
) as src 
ON dst.ColumnA = src.ColumnE AND 
    dst.ColumnB = src.ColumnF AND 
    dst.ColumnC = src.ColumnG 
WHEN NOT MATCHED THEN 
    INSERT(
     ColumnA, 
     ColumnB, 
     ColumnC, 
     ColumnD 
    ) VALUES (
     src.ColumnE, 
     src.ColumnF, 
     src.ColumnG, 
     GETDATE() 
    ) 
WHEN MATCHED THEN UPDATE 
    SET 
     dst.ColumnD = GETDATE() 
OUTPUT 
    deleted.ColumnA, 
    deleted.ColumnB, 
    deleted.ColumnC, 
    deleted.ColumnD, 
    $action AS action 
INTO 
    @Updated; 

SELECT * FROM @Updated WHERE Action = 'UPDATE' -- List replaced rows from the Table1