usar update matched into example delete como sql-server merge sql-server-2008-r2 upsert

update - ¿Qué es USAR en la sintaxis de SQL Server 2008 MERGE?



sql server merge example insert update (3)

Jacob hizo la pregunta perfecta: dame la sintaxis de MERGE .

Cada respuesta por ahí salta inmediatamente al caso más complicado que se pueda imaginar; oscureciendo la sintaxis con extraña confusión.

Marc dio una respuesta :

MERGE member_topic AS target USING someOtherTable AS source ON target.mt_member = source.mt_member AND source.mt_member = 0 AND source.mt_topic = 110 WHEN MATCHED THEN UPDATE SET mt_notes = ''test'' WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, ''test'') ;

Viendo esta respuesta, estoy tan confundido como Jacob estaba:

No tengo otra tabla

Marc sugirió que someOtherTable es un valor de marcador de posición ficticio, no importa que no tengas esa tabla.

Lo intento, y SQL Server se queja.

Nombre de objeto no válido ''someOtherTable''.

Eso me deja luchando para entender para qué sirve USING en USING foo si no es importante (excepto realmente importante).

¿Qué está utilizando USING cuando usa foo cuando uso la sintaxis de SQL Server 2008 MERGE?

Pregunta extra

¿Cuál es la sintaxis de UPSERT utilizando MERGE?

IF (rowExists) UPDATE Users SET Firstname=''Ian'', LastName=''Boyd'' WHERE Username=''iboyd'' ELSE INSERT INTO Users (UserGUID, Username, FirstName, LastName, AuthenticationMethod) VALUES (''{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}'', ''iboyd'', ''Ian'', ''Boyd'', ''Windows'')

se convierte (código exacto que probé):

begin transaction MERGE Users USING foo ON Users.UserName = foo.UserName WHEN MATCHED THEN UPDATE SET Firstname = foo.FirstName, Lastname = foo.LastName WHEN NOT MATCHED THEN INSERT (UserGUID, Username, FirstName, LastName, AuthenticationMethod) VALUES (''{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}'', ''iboyd'', ''Ian'', ''Boyd'', ''Windows'') ; --A MERGE statement must be terminated by a semi-colon (;). rollback Msg 208, Level 16, State 1, Line 3 Invalid object name ''foo''.

?

Con una tabla de Users que contiene las columnas:

UserGUID uniqueidentifier Username varchar(50) FirstName varchar(50) LastName varchar(50) AuthenticationMethod varchar(50)

Actualizar:

USING <table_source>

Donde table_source es:

table_or_view_name [ [ AS ] table_alias ] [ <tablesample_clause> ] [ WITH ( table_hint [ [ , ]...n ] ) ] | rowset_function [ [ AS ] table_alias ] [ ( bulk_column_alias [ ,...n ] ) ] | user_defined_function [ [ AS ] table_alias ] | OPENXML <openxml_clause> | derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ] | <joined_table> | <pivoted_table> | <unpivoted_table>

Donde joined_table es:

indefinido

Donde pivoted_table es:

indefinido

Donde unpivoted_table es:

indefinido


La tabla de origen puede ser cualquier cosa, como:

MERGE member_topic AS target USING (SELECT @Variable1, @Variable2, @Variable3) AS source(Col1, Col2, Col3) ON target.mt_member = source.Col1 AND source.Col1 = 0 AND source.Col2 = 110 WHEN MATCHED THEN UPDATE SET mt_notes = ''test'' WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, ''test'');

Obviamente, en la selección de fuente anidada puedes hacer muchas más cosas. Seleccione de una vista, una función, una variable de tabla, un CTE incluso.

En cuanto a la pregunta extra, respondiste tu propia pregunta.

A veces, para tablas muy grandes, también uso la sugerencia ROWLOCK en la tabla de destino, para al menos intentar no bloquear toda la tabla en caso de actualizaciones:

MERGE member_topic WITH (ROWLOCK) AS target

En relación con la pregunta de bonificación no funciona, aquí hay una muestra de trabajo. Cambié el nombre de algunos de los objetos, por supuesto.

DECLARE @Variable1 AS INT; SET @Variable1 = 1234; MERGE dbo.Table1 WITH(ROWLOCK) target USING(SELECT @Variable1) source(Key) ON target.[Key] = source.[Key] WHEN MATCHED THEN UPDATE SET Col1 = @SomeVar1, Col2 = @SomeVar2 WHEN NOT MATCHED THEN INSERT ([Key] ,[Col1] ,[Col2]) VALUES (@Variable1 ,@SomeVar1 ,@SomeVar2);


Siguiendo con la respuesta de Martin Smith, puede aumentar varias filas de valores explícitos a la vez simplemente repitiendo los corchetes, separándolos con una coma, por ejemplo,

MERGE Users WITH (HOLDLOCK) USING (VALUES (''{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}'', ''iboyd'', ''Ian'', ''Boyd'', ''Windows''), (''{00000DC5-7A3E-4F1A-82C6-8EF452D2DE66}'', ''jsmith'', ''John'', ''Smith'', ''ActiveDirectory'')) AS foo(UserGUID, Username, FirstName, LastName, AuthenticationMethod) ON Users.UserName = foo.UserName WHEN MATCHED THEN UPDATE SET Firstname = foo.FirstName, Lastname = foo.LastName WHEN NOT MATCHED THEN INSERT (UserGUID, Username, FirstName, LastName, AuthenticationMethod) VALUES (UserGUID, Username, FirstName, LastName, AuthenticationMethod);

Probé esto en SQL Server 2012. (Habría agregado esto como un comentario pero demasiados caracteres).

Agregué un HOLDLOCK después de ver this , porque si está utilizando MERGE para UPSERT, seguramente el punto se está bloqueando, la sintaxis no está más clara. Vea también el comentario de Marcel sobre ROWLOCK para tablas grandes.

Hubo otro post que encontré más claro que el promedio, también.


Una combinación tiene un origen de tabla y una tabla de destino. Esto introduce la tabla de origen (que no necesita ser una tabla física real, solo un conjunto de resultados).

La gramática está indicada en tu pregunta. Para combinar desde otra tabla o vista use

MERGE Users USING SomeOtherTableName AS foo /*Alias is optional*/ ON /* ... */

O puedes usar <unpivoted_table> por ejemplo

MERGE Users USING master..spt_values UNPIVOT (X FOR Y IN ([high],[low])) AS foo ON Users.Username = foo.Y WHEN MATCHED THEN UPDATE SET FirstName = foo.Y WHEN NOT MATCHED THEN INSERT (UserGUID, Username, FirstName, LastName, AuthenticationMethod) VALUES (foo.Y, foo.Y, foo.Y, foo.Y, foo.Y);

Para su pregunta de bonificación, puede usar la cláusula VALUES aquí como parte de la opción de derived_table .

MERGE Users USING (VALUES (''{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}'', ''iboyd'', ''Ian'', ''Boyd'', ''Windows'')) AS foo(UserGUID, Username, FirstName, LastName, AuthenticationMethod) ON Users.UserName = foo.UserName WHEN MATCHED THEN UPDATE SET Firstname = foo.FirstName, Lastname = foo.LastName WHEN NOT MATCHED THEN INSERT (UserGUID, Username, FirstName, LastName, AuthenticationMethod) VALUES (UserGUID, Username, FirstName, LastName, AuthenticationMethod);