Estoy tratando de actualizar una tabla con una matriz de valores. Cada elemento de la matriz contiene información que coincide con una fila en una tabla en la base de datos de SQL Server. Si la fila ya existe en la tabla, actualizamos esa fila con la información en la matriz dada. De lo contrario, insertamos una nueva fila en la tabla. Básicamente he descrito upsert.
Ahora, estoy tratando de lograr esto en un procedimiento almacenado que toma un parámetro XML. La razón por la que estoy usando XML y no un parámetro con valores de tabla es porque, al hacer esto último, tendré que crear un tipo personalizado en SQL y asociar este tipo al procedimiento almacenado. Si alguna vez cambiara algo en mi procedimiento almacenado o mi esquema db en el futuro, tendría que rehacer tanto el procedimiento almacenado como el tipo personalizado. Quiero evitar esta situación. Además, la superioridad que tiene TVP sobre XML no es útil para mi situación porque mi tamaño de matriz de datos nunca excederá 1000. Esto significa que no puedo usar la solución propuesta aquí: Cómo insertar múltiples registros usando XML en SQL Server 2008
Además, una discusión similar aquí ( UPSERT - ¿Hay una mejor alternativa para MERGE o @@ rowcount? ) Es diferente de lo que estoy preguntando porque estoy tratando de insertar varias filas en una tabla.
Tenía la esperanza de que simplemente usaría el siguiente conjunto de consultas para insertar los valores del xml. Pero esto no va a funcionar. Se supone que este enfoque solo funciona cuando la entrada es una sola fila.
begin tran
update table with (serializable) set select * from xml_param
where key = @key
if @@rowcount = 0
begin
insert table (key, ...) values (@key,..)
end
commit tran
La siguiente alternativa es usar un SI exhaustivo EXISTE o una de sus variaciones de la siguiente forma. Pero, rechazo esto por ser de eficiencia subóptima:
IF (SELECT COUNT ... ) > 0
UPDATE
ELSE
INSERT
La siguiente opción fue usar la instrucción Merge como se describe aquí: http://www.databasejournal.com/features/mssql/using-the-merge-statement-to-perform-an-upsert.html . Pero, luego leí sobre problemas con la consulta de fusión aquí: http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ . Por esta razón, estoy tratando de evitar la fusión.
Entonces, mi pregunta es: ¿hay alguna otra opción o una mejor manera de lograr una respuesta múltiple múltiple usando el parámetro XML en el procedimiento almacenado de SQL Server 2008?
Tenga en cuenta que los datos en el parámetro XML pueden contener algunos registros que no se deben UPSERT debido a que son más antiguos que el registro actual. Hay un ModifiedDate
campo tanto en el XML como en la tabla de destino que debe compararse para determinar si el registro debe actualizarse o descartarse.
MERGE
que Bertrand señala son en su mayoría casos extremos e ineficiencias, no muestran obstáculos: MS no lo habría lanzado si fuera un verdadero campo minado. ¿Estás seguro de que las convoluciones por las que estás pasando para evitar MERGE
no están creando más errores potenciales de los que están guardando?
MERGE
. Los pasos INSERTAR y ACTUALIZAR de MERGE aún se procesan por separado. La principal diferencia en mi enfoque es la variable de tabla que contiene los ID de registro actualizados y la consulta DELETE que usa esa variable de tabla para eliminar esos registros de la tabla temporal de los datos entrantes. Y supongo que la FUENTE podría ser directa desde @ XMLparam.nodes () en lugar de volcar a una tabla temporal, pero aún así, eso no es un montón de cosas adicionales para no tener que preocuparse de encontrarse en uno de esos casos extremos; )