Cómo solucionar este problema de procedimiento almacenado

sql sqlbulkcopy sql-server

Pregunta

Tengo 2 mesas. Las siguientes son solo una versión simplificada de estas tablas.

TableA
Id <pk> incrementing
Name varchar(50)

TableB
TableAId <pk> non incrementing
Name varchar(50)

Ahora estas tablas tienen una relación entre sí.

Guión

El usuario 1 llega a mi sitio y realiza algunas acciones (en este caso, agrega filas a la Tabla A). Así que uso un SqlBulkCopy todos estos datos en la Tabla A.

Sin embargo, necesito agregar los datos también a la Tabla B, pero no sé los Id's recién creados de la Tabla A, ya que SQLBulkCopy no los devolverá.

Así que estoy pensando en tener un procedimiento almacenado que encuentre todos los ID que no existen en la Tabla B y luego los inserte.

INSERT INTO TableB (TableAId , Name)
SELECT Id,Name FROM TableA as tableA
WHERE not exists( ...)

Sin embargo, esto viene con un problema. Un usuario en cualquier momento puede eliminar algo de la TablaB, por lo que si un usuario elimina una fila y luego aparece otro usuario o incluso aparece el mismo usuario y hace algo en la Tabla A, mi procedimiento almacenado devolverá esa fila eliminada en la Tabla B. Dado que seguirá existiendo en la Tabla A pero no en la Tabla B y, por lo tanto, cumplirá con la condición del procedimiento almacenado.

Entonces, ¿hay una mejor manera de lidiar con dos tablas que deben actualizarse cuando se utiliza la inserción masiva?

Respuesta aceptada

SQLBulkCopy complica esto, por lo que consideraría usar una tabla de etapas y una cláusula OUTPUT

Ejemplo, en una mezcla de pseudo código de cliente y SQL.

create SQLConnection

Create #temptable
Bulkcopy to #temptable

Call proc on same SQLConnection

proc:
   INSERT tableA (..)
   OUTPUT INSERTED.key, .. INTO TableB
   SELECT .. FROM #temptable

close connection

Notas:

  • Temptable será local a la conexión y estará aislado.

  • Las escrituras a A y B serán atómicas.
  • la superposición o las escrituras posteriores no se preocupan por lo que suceda más tarde a A y B
  • enfatizando el último punto, A y B solo se rellenarán del conjunto de filas en #temptable

Alternativa:

Agregue otra columna a A y B llamada sessionid y utilícela para identificar los lotes de filas.


Respuesta popular

Al igual que una solución alternativa, puede utilizar los activadores de la base de datos para actualizar la segunda tabla.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué