2009-09-16 36 views
14

Fuente TablaProblemas con la instrucción MERGE SQL Server

Id, Name, Address 
1 A  #202 
1 A  #203 
1 A  #204 
2 A  #202 

tabla de objetivos

después de combinación

Id, Name, Address 
1 A  #202 
2 A  #202 

estoy usando este SQL

create table #S (ID int, Name varchar(25) NULL, Address varchar(25) NULL) 
create table #T (ID int, Name varchar(25) NULL, Address varchar(25) NULL) 

INSERT #S values(1, 'A', '#202') 
INSERT #S values(1, 'A', '#203') 
INSERT #S values(1, 'A', '#203') 
INSERT #S values(1, 'A', '#204') 

INSERT #T values(1, 'A', NULL) 

MERGE #T USING 
    (
Select id, name, address 
from #S 
) AS S(id,name,address) 
on #T.id=S.id and #T.Name=S.Name 
when not matched THEN 
    INSERT values(S.id,S.Name, S.Address) 
when matched then 
    update set Address = S.Address; 
GO 

Select * from #T 
GO 

Select * from #S 
GO 

Esto provoca un error

Msg 8672, nivel 16, estado 1, línea 18
La instrucción MERGE intentó actualizar o borrar la misma fila más de una vez. Esto sucede cuando una fila de destino coincide con más de una fila fuente. Una instrucción MERGE no puede ACTUALIZAR/ELIMINAR la misma fila de la tabla objetivo varias veces. Refina la cláusula ON para garantizar que una fila objetivo coincida como máximo con una fila fuente, o utiliza la cláusula GROUP BY para agrupar las filas fuente.

Quiero actualizar la fila en A con el valor de Dirección de cualquiera de los tres valores coincidentes. ¿Como hacer esto?

Respuesta

22

Cualquiera de los cuatro valores en #S coincidirá con el valor de fila única de la tabla de destino (todos los valores en #S tienen id = 1 y name = 'A' - por lo que todos coinciden con la única fila en el destino), así el valor se actualizará cuatro veces; eso es lo que dice el error, y es absolutamente correcto.

¿Qué es lo que realmente quieres lograr aquí?

¿Desea establecer la dirección en el primero de los valores de la tabla de origen? Utilice una cláusula en su TOP 1 subselección:

MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S) AS S 
ON #T.id = S.id AND #T.Name = S.Name 
WHEN NOT MATCHED THEN 
    INSERT VALUES(S.id,S.Name, S.Address) 
WHEN MATCHED THEN 
    UPDATE SET Address = S.Address; 

¿Quieres configurar la dirección a un elemento aleatorio de los valores de la tabla de origen? Utilice una cláusula TOP 1 y ORDER BY NEWID() en su subselección:

MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S ORDER BY NEWID()) AS S 
ON #T.id = S.id AND #T.Name = S.Name 
WHEN NOT MATCHED THEN 
    INSERT VALUES(S.id,S.Name, S.Address) 
WHEN MATCHED THEN 
    UPDATE SET Address = S.Address; 

Si coinciden con cuatro filas de origen a una sola fila de destino, que no se consigue un resultado útil - lo que necesita saber lo que realmente quiere.

Marc

+0

Quiero actualizar la fila A con valor de Dirección de cualquiera de los tres valores coincidentes –

+2

, pero ¿cómo se determina cuál de ellos usar? – HLGEM

+2

Utilicé Row_Number es tanto el origen como el destino (vista). A continuación, los criterios de coincidencia incluían una condición adicional, si los números pares son iguales junto con (dirección.destino isnull o (dirección.txt = dirección.s)) –

1

Retire la dupicate usando

select R.* 
from (SELECT Customer,Material,Received_date_time, 
row_number() over (Partition by Customer, Material 
order by Customer,Material,Received_date_time) as rn 
     from Customer_Table WHERE Status=0  
    ) as R 
where R.rn = 1 

de fusión no se puede tener duplicados, por lo que siempre tiene que recoger la última

+0

Dependiendo del caso, esto tiene más sentido. Tal vez puedas agregar una restricción única. –

Cuestiones relacionadas