tsql - w3schools - ACTUALIZACIÓN-no-op en la sentencia SQL MERGE
merge to tables in sql (1)
Tengo una tabla con algunos datos persistentes en ella. Ahora, cuando lo pregunto, también tengo un CTE bastante complejo que calcula los valores requeridos para el resultado y necesito insertar las filas que faltan en la tabla persistente. Al final, quiero seleccionar el resultado que consiste en todas las filas identificadas por el CTE pero con los datos de la tabla si ya estaban en la tabla, y necesito la información si una fila se acaba de insertar o no.
Simplificado, esto funciona así (el siguiente código se ejecuta como una consulta normal si desea intentarlo):
-- Set-up of test data, this would be the persisted table
DECLARE @target TABLE (id int NOT NULL PRIMARY KEY) ;
INSERT INTO @target (id) SELECT v.id FROM (VALUES (1), (2)) v(id);
-- START OF THE CODE IN QUESTION
-- The result table variable (will be several columns in the end)
DECLARE @result TABLE (id int NOT NULL, new bit NOT NULL) ;
WITH Source AS (
-- Imagine a fairly expensive, recursive CTE here
SELECT * FROM (VALUES (1), (3)) AS Source (id)
)
MERGE INTO @target AS Target
USING Source
ON Target.id = Source.id
-- Perform a no-op on the match to get the output record
WHEN MATCHED THEN
UPDATE SET Target.id=Target.id
WHEN NOT MATCHED BY TARGET THEN
INSERT (id) VALUES (SOURCE.id)
-- select the data to be returned - will be more columns
OUTPUT source.id, CASE WHEN $action=''INSERT'' THEN CONVERT(bit, 1) ELSE CONVERT(bit, 0) END
INTO @result ;
-- Select the result
SELECT * FROM @result;
No me gusta la parte de WHEN MATCHED THEN UPDATE
, prefiero dejar la actualización redundante, pero luego no obtengo la fila de resultados en la cláusula OUTPUT
.
¿Es esta la manera más eficiente de completar y devolver este tipo de datos?
¿O habría una solución más eficiente sin MERGE
, por ejemplo, al calcular previamente el resultado con un SELECT
y luego realizar un INSERT
de las filas que son new=0
? Tengo dificultades para interpretar el plan de consulta, ya que básicamente se reduce a una "Fusión de índice agrupado" que es bastante vaga para mi rendimiento en comparación con el SELECT
separado seguido de la variante INSERT
. Y me pregunto si SQL Server (2008 R2 con CU1) es realmente lo suficientemente inteligente como para ver que la UPDATE
es una no operación (por ejemplo, no se requiere escritura).
Podría declarar una variable ficticia y establecer su valor en la cláusula WHEN MATCHED.
DECLARE @dummy int;
...
MERGE
...
WHEN MATCHED THEN
UPDATE SET @dummy = 0
...
Creo que debería ser menos costoso que la actualización de la tabla real.