Consulta sobre INSERT...SELECT y UPDATES

09/02/2007 - 13:55 por J.A. García Barceló | Informe spam
Buenos dias,

Tengo un procedimiento almacenado que realiza una serie de cálculos
periódicamente sobre una tabla temporal #WorkingTable para finalmente grabar
los datos finales sobre la tabla definitiva FinalTable. El caso es que
aunque el SP se ejecuta mediante el agente cada hora, sólo algunos cientos
de filas sobre un total de aprox. 4000 cambian realmente entre ejecución y
ejecución.

Actualmente y para simplificar, el SP hace algo así (K1 y K2 son campos de
una clave primaria compuesta):

DELETE FROM FinalTable
INSERT INTO FinalTable (K1, K2, Valor)
SELECT K1, K2, Valor FROM #WorkingTable

Esto funciona sin problemas pero para optimizar ancho de banda (estamos
usando replicación a través de una VPN de ancho de banda reducido) me
gustaría evitar tener que hacer el DELETE y luego el INSERT de unos datos
que son casi todos iguales.

A costa de un peor rendimiento en local, pero con la idea de optimizar ancho
de banda me gustaría hacer algo asi:

INSERT INTO FinalTable (K1, K2, Valor)
SELECT K1, K2, Valor FROM #WorkingTable WHERE **problema**
están en una tabla y no en la otra?

DELETE FROM FinalTable
WHERE ** mas de lo mismo**
FinalTable y que deben ser borrados?

UPDATE FinalTable SET Valor = #WorkingTable.Valor
FROM FinalTable INNER JOIN #WorkingTable
ON FinalTable.K1 = #WorkingTable.K1 AND
FinalTable.K2 = #WorkingTable.K2 AND
FinalTable.Valor <> #WorkingTable.Valor

La única solucion que se me ocurre para solucionar el problema de los
INSERTs y DELETEs selectivos es crear un nuevo campo autonumérico y cambiar
la clave primaria para que sea este único campo, pero me gustaría saber si
existe alguna construcción que me permita hacer lo que necesito sin cambiar
el esquema.

Muchas gracias y un saludo a todos.

J.A. García Barceló
http://jagbarcelo.blogspot.com
 

Leer las respuestas

#1 Alejandro Mesa
09/02/2007 - 14:54 | Informe spam
J.A. García Barceló,

INSERT INTO FinalTable (K1, K2, Valor)
SELECT K1, K2, Valor FROM #WorkingTable WHERE **problema**
están en una tabla y no en la otra?



Puedes usar el operador EXISTS.

INSERT INTO FinalTable (K1, K2, Valor)
SELECT K1, K2, Valor
FROM #WorkingTable as wt
where not exists (
select *
from FinalTable as ft
where ft.k1 = wt.k1 and ft.k2 = wt.k2
)

DELETE FROM FinalTable
WHERE ** mas de lo mismo**
FinalTable y que deben ser borrados?



DELETE FROM FinalTable
where not exists (
select *
from #WorkingTable as wt
where wt.k1 = FinalTable.k1 and wt.k2 = FinalTable.k2
)


UPDATE FinalTable SET Valor = #WorkingTable.Valor
FROM FinalTable INNER JOIN #WorkingTable
ON FinalTable.K1 = #WorkingTable.K1 AND
FinalTable.K2 = #WorkingTable.K2 AND
FinalTable.Valor <> #WorkingTable.Valor



UPDATE
FinalTable
SET
Valor = #WorkingTable.Valor
FROM
FinalTable INNER JOIN #WorkingTable
ON FinalTable.K1 = #WorkingTable.K1 AND
FinalTable.K2 = #WorkingTable.K2
WHERE
FinalTable.Valor <> #WorkingTable.Valor

or
(
(FinalTable.Valor is null and #WorkingTable.Valor is not null)
or
(FinalTable.Valor is not null and #WorkingTable.Valor is null)
)


AMB

"J.A. García Barceló" wrote:

Buenos dias,

Tengo un procedimiento almacenado que realiza una serie de cálculos
periódicamente sobre una tabla temporal #WorkingTable para finalmente grabar
los datos finales sobre la tabla definitiva FinalTable. El caso es que
aunque el SP se ejecuta mediante el agente cada hora, sólo algunos cientos
de filas sobre un total de aprox. 4000 cambian realmente entre ejecución y
ejecución.

Actualmente y para simplificar, el SP hace algo así (K1 y K2 son campos de
una clave primaria compuesta):

DELETE FROM FinalTable
INSERT INTO FinalTable (K1, K2, Valor)
SELECT K1, K2, Valor FROM #WorkingTable

Esto funciona sin problemas pero para optimizar ancho de banda (estamos
usando replicación a través de una VPN de ancho de banda reducido) me
gustaría evitar tener que hacer el DELETE y luego el INSERT de unos datos
que son casi todos iguales.

A costa de un peor rendimiento en local, pero con la idea de optimizar ancho
de banda me gustaría hacer algo asi:

INSERT INTO FinalTable (K1, K2, Valor)
SELECT K1, K2, Valor FROM #WorkingTable WHERE **problema**
están en una tabla y no en la otra?

DELETE FROM FinalTable
WHERE ** mas de lo mismo**
FinalTable y que deben ser borrados?

UPDATE FinalTable SET Valor = #WorkingTable.Valor
FROM FinalTable INNER JOIN #WorkingTable
ON FinalTable.K1 = #WorkingTable.K1 AND
FinalTable.K2 = #WorkingTable.K2 AND
FinalTable.Valor <> #WorkingTable.Valor

La única solucion que se me ocurre para solucionar el problema de los
INSERTs y DELETEs selectivos es crear un nuevo campo autonumérico y cambiar
la clave primaria para que sea este único campo, pero me gustaría saber si
existe alguna construcción que me permita hacer lo que necesito sin cambiar
el esquema.

Muchas gracias y un saludo a todos.

J.A. García Barceló
http://jagbarcelo.blogspot.com



Preguntas similares