2017-02-04 5 views
2

У меня возникла ситуация, когда у меня есть процедура хранения, содержащая оператор слияния. Процедура захватывает данные из таблицы A и использует оператор слияния для обновления определенных записей в таблице B. Процедура работает нормально, но иногда есть экземпляры, где в таблице указаны повторяющиеся записи. Процедура хранилища находится в пакете с набором уведомлений об ошибках и пакет работает в задании, и он дает ошибку ниже. Есть ли способы отладить это? Как некоторые, где в процедуре магазина говорят, что если она дает ошибку, тогда вставьте исходные данные в таблицу? Любой вход оценивается.Ошибка слияния Ошибка отладки

Благодаря

Ошибка:

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

Посмотрите на DISTINCT или агрегировать строки в таблице А, до слияния так соединяющий ключ (ы) заканчивает каждый, идентифицируя уникальный ряд. – VBlades

ответ

2

Вы можете добавить что-то вроде этого в начале вашей процедуры слияния: установки

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 

фиктивная процедура:

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 

выполнить тест-процедурный и проверьте ошибки таблицу:

exec dbo.Merge_A_into_B 

select * 
from merge_err 
where cnt > 1 

результаты:

+----+----------+----------+----+-----+---------------------+ 
| 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 | 
+----+----------+----------+----+-----+---------------------+ 

 Смежные вопросы

  • Нет связанных вопросов^_^