2009-07-29 28 views
43

En MySQL, si especifica ON DUPLICATE KEY UPDATE y se inserta una fila que causaría un valor duplicado en un índice UNIQUE o PRIMARY KEY, se realizará una ACTUALIZACIÓN de la fila anterior. Por ejemplo, si la columna se declara como un único y contiene el valor 1, los siguientes dos comandos tienen efecto idéntico:SQL Server ofrece algo como MySQL ON DUPLICATE KEY UPDATE

INSERT INTO table (a,b,c) VALUES (1,2,3) 
    ON DUPLICATE KEY UPDATE c=c+1; 

UPDATE table SET c=c+1 WHERE a=1; 

no creo que me he encontrado nada por el estilo de T-SQL. ¿SQL Server ofrece algo comparable a la ACTUALIZACIÓN DE LLAVE DUPLICADA de MySQL?

+0

Puede simularlo con un procedimiento almacenado. No tengo el código exacto fuera de mi cabeza. –

+0

@Robert Harvey: siempre realicé la operación comprobando si existe la fila. En caso afirmativo, realice una actualización, sino inserte una nueva fila. ¿Eso es lo que estabas pensando también? –

Respuesta

35

No hay una llave duplicada equivalente actualización, pero se fusionan y cuando se combina podría funcionar para usted

Inserting, Updating, and Deleting Data by Using MERGE

+11

Solo tenga en cuenta que MERGE no es inmune a la colisión de inserción de alta concurrencia. ** Debes ** usar ** WITH (UPDLOCK, HOLDLOCK) para fusionar y no colisionar. Algunos sistemas de transacciones ultra altas por segundo usan una estrategia diferente donde los bloqueos no se usan, pero cualquier error se atrapa y luego se convierte en una actualización. – ErikE

+3

este nombre de usuario merece más votos. – Pete

2

SQL Server 2008 tiene esta característica, como parte de TSQL.
ver la documentación de instrucción MERGE aquí - http://msdn.microsoft.com/en-us/library/bb510625.aspx

+1

Solo tenga en cuenta que MERGE no es inmune a la colisión de inserción de alta concurrencia. Debe usar WITH (UPDLOCK, HOLDLOCK) para fusionarse y no colisionar. Algunos sistemas de transacciones ultra altas por segundo usan una estrategia diferente donde los bloqueos no se usan, pero cualquier error se atrapa y luego se convierte en una actualización. – ErikE

16

Me sorprendió que ninguna de las respuestas en esta página contenía un ejemplo de una consulta real, así que aquí vamos:

Un ejemplo más complejo de la inserción de datos y luego Gestión de duplicados

MERGE 
INTO MyBigDB.dbo.METER_DATA WITH (HOLDLOCK) AS target 
USING (SELECT 
    77748 AS rtu_id 
    ,'12B096876' AS meter_id 
    ,56112 AS meter_reading 
    ,'20150602 00:20:11' AS local_time) AS source 
(rtu_id, meter_id, meter_reading, time_local) 
ON (target.rtu_id = source.rtu_id 
    AND target.time_local = source.time_local) 
WHEN MATCHED 
    THEN UPDATE 
     SET meter_id = '12B096876' 
     ,meter_reading = 56112 
WHEN NOT MATCHED 
    THEN INSERT (rtu_id, meter_id, meter_reading, time_local) 
     VALUES (77748, '12B096876', 56112, '20150602 00:20:11'); 
+4

Usted señor ... es un salvavidas. Realmente odio las documentaciones de Microsoft ... siempre dan todos los ejemplos, excepto los que se utilizan con más frecuencia – Tschallacka

+0

' 'se funden en MyFancyTableName CON (HOLDLOCK) como destino \t \t \t USANDO \t \t \t (selección: Identificación como identificación, : lastaccess AS lastaccess) como fuente de \t \t \t (id, lastaccess) \t \t \t EN \t \t \t (target.id = fuente.id) \t \t \t cuando se combina luego actualizar SET lastaccess =: lastaccess2 \t \t \t Si la alineación no luego insertar (id, lastaccess) \t \t \t VALORES (: ID2,: lastaccess3); '' ¿Es necesario para publicar tanto variables en 'USING' seleccionar o simplemente el 'id' sería suficiente allí? – Tschallacka

+0

Gracias por la referencia al comando Fusionar. Debo señalar que en las DECLARACIONES CONJUNTAS está utilizando los mismos valores que ha definido como fuente. Por lo tanto, si desea realizar una actualización de muchos registros, debe asignar el valor de origen de la siguiente manera: –

Cuestiones relacionadas