2017-02-04 1 views
2

J'ai une situation dans laquelle une procédure de magasin contient une instruction de fusion. La procédure récupère les données de la table A et utilise l'instruction de fusion pour mettre à jour certains enregistrements dans la table B. La procédure fonctionne correctement mais parfois, il existe des instances dans lesquelles des enregistrements sont dupliqués dans la table A. et le paquet s'exécute dans un travail et il donne l'erreur ci-dessous. Existe-t-il des moyens de déboguer cela? Comme certains où dans la procédure de magasin dire si elle donne une erreur, puis insérer les données source dans une table? Toute contribution est appréciée.Débogage de l'instruction d'instruction de fusion

Merci

Erreur:

failed with the following error: "The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.

+0

Regardez à DISTINCT ou agréger les lignes dans le tableau A avant la fusion pour la joindre la clé (s) finissent par identifier une rangée unique. – VBlades

Répondre

2

Vous pouvez ajouter quelque chose comme ça au début de votre procédure de fusion:

configuration de test
if exists (
    select 1 
    from a 
    group by a.OnColumn 
    having count(*)>1 
    ) 
    begin; 
    insert into merge_err (OnColumn, OtherCol, rn, cnt) 
     select 
      a.OnColumn 
     , a.OtherCol 
     , rn = row_number() over (
      partition by OnColumn 
      order by OtherCol 
      ) 
     , cnt = count(*) over (
      partition by OnColumn 
      ) 
     from a 
    raiserror('Duplicates in source table a', 0, 1) 
    return -1; 
    end; 

: http://rextester.com/EFZ77700

create table a (OnColumn int, OtherCol varchar(16)) 
insert into a values 
    (1,'a') 
    , (1,'b') 
    , (2,'c') 

create table b (OnColumn int primary key, OtherCol varchar(16)) 
insert into b values 
    (1,'a') 
    , (2,'c') 


create table merge_err (
    id int not null identity(1,1) primary key clustered 
    , OnColumn int 
    , OtherCol varchar(16) 
    , rn int 
    , cnt int 
    , ErrorDate datetime2(7) not null default sysutcdatetime() 
); 

go 

procédure fictive:

create procedure dbo.Merge_A_into_B as 
begin 
set nocount, xact_abort on; 
if exists (
    select 1 
    from a 
    group by a.OnColumn 
    having count(*)>1 
    ) 
    begin; 
    insert into merge_err (OnColumn, OtherCol, rn, cnt) 
     select 
      a.OnColumn 
     , a.OtherCol 
     , rn = row_number() over (
      partition by OnColumn 
      order by OtherCol 
      ) 
     , cnt = count(*) over (
      partition by OnColumn 
      ) 
     from a 
    raiserror('Duplicates in source table a', 0, 1) 
    return -1; 
    end; 

/* 
merge into b 
    using a 
    on b.OnColumn = a.OnColumn 
    ... 
--*/ 
end; 
go 

exécuter proc test et vérifier la table d'erreur:

exec dbo.Merge_A_into_B 

select * 
from merge_err 
where cnt > 1 

résultats:

+----+----------+----------+----+-----+---------------------+ 
| id | OnColumn | OtherCol | rn | cnt |  ErrorDate  | 
+----+----------+----------+----+-----+---------------------+ 
| 1 |  1 | a  | 1 | 2 | 05.02.2017 17:22:39 | 
| 2 |  1 | b  | 2 | 2 | 05.02.2017 17:22:39 | 
+----+----------+----------+----+-----+---------------------+