2016-12-17 3 views
1

У меня есть исходная таблица, называемая payroll в промежуточной базе данных. Я использую оператор Merge, который вставляет данные сотрудников из базы Staging to Expense. После того, как сотрудники женятся и их фамилия меняется, я получаю эту ошибку:Заявление о слиянии с сообщением об ошибке после изменения фамилии в таблице источников

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.

У меня есть уникальный индекс EmployeeIDEmployee в таблице. Например, один месяц я получаю файл с уникальным идентификатором имени 10072 имени Эбби и фамилией кузнец, когда Эбби выходит замуж за изменения ее фамилии в Маршалл, но с тем же именем и идентификатором сотрудника. Что мне делать?

Вот мое заявление о слиянии.

MERGE INTO Dimension.Employee AS T 
     USING 
      (
       SELECT DISTINCT 
        LTRIM(RTRIM(EmplID)) AS EmployeeID 
        ,LTRIM(RTRIM(FirstName)) AS FirstName 
        ,LTRIM(RTRIM(LastName)) AS LastName 
       FROM Staging.PayRoll 
      ) AS S 
      ON T.EmployeeID = S.EmployeeID 
       WHEN NOT MATCHED THEN 
        INSERT (EmployeeID, FirstName, LastName) 
        VALUES (S.EmployeeID, S.FirstName, S.LastName) 
       WHEN MATCHED THEN UPDATE SET 
        T.FirstName = S.FirstName 
        , T.LastName = S.LastName 
        ; 
+0

все ли какие-либо противопоказания на столе? – GurV

+1

Не используйте MERGE для этого; используйте отдельные инструкции INSERT и UPDATE ... вы слишком усложняете ситуацию! – gvee

ответ

1

Похоже, этот бит кода генерирует 2 строки для того же идентификатора, когда имя изменяется таблица расчета заработной платы имеет 2 EmpIDs.

  SELECT DISTINCT 
       LTRIM(RTRIM(EmplID)) AS EmployeeID 
       ,LTRIM(RTRIM(FirstName)) AS FirstName 
       ,LTRIM(RTRIM(LastName)) AS LastName 
      FROM Staging.PayRoll 

Операция слияния затем пытается обновить одну и ту же строку в таблице целей дважды. Теоретически вы не можете этого сделать, потому что SQL может возвращать данные в любом ORDER, чтобы вы не могли применить ваши 2 обновления в правильной последовательности.

Ниже приведен пример ошибки и возможного решения. (извините, у меня недостаточно информации о таблице зарплат, чтобы предоставить что-либо еще)

DROP TABLE #Payroll 
CREATE TABLE #Payroll (ID INT 
        ,EmplID INT 
        ,Name VARCHAR(10) 
        ) 

INSERT INTO #Payroll VALUES 
(1,10,'Bill') 
,(2,10,'Bill') 
,(3,20,'John') 
,(4,20,'John') 
,(5,30,'Stephen') 
,(6,30,'Steven') --EmpID 30 changes his name 

--Steven changed name, but the query is generating a duplicate the MERGE will not be happy 
SELECT DISTINCT 
    LTRIM(RTRIM(EmplID)) AS EmployeeID 
    ,LTRIM(RTRIM(Name)) AS FirstName 
FROM #Payroll 

--Solution 
SELECT DISTINCT 
    LTRIM(RTRIM(P.EmplID)) AS EmployeeID 
    ,LTRIM(RTRIM(P.Name)) AS FirstName 
FROM #Payroll P 
    CROSS APPLY (SELECT TOP 1 * FROM #Payroll T 
       WHERE T.EmplID = P.EmplID 
       ORDER BY ID DESC) L 
WHERE 
    L.ID = P.ID 
+0

Так что я должен изменить в коде? – Justin

+0

Запустите этот бит запроса в таблице Payroll, если вы возвращаете дубликаты идентификаторов, тогда нам нужно найти способ исключения старой версии записи. – pacreely

+0

см. Дополнительный пример, который я добавил – pacreely