Looping en Trigger?

sqlbulkcopy sql-server-2008 triggers

Pregunta

Tengo este siguiente escenario,

Hay cuatro mesas PAÍS, ESTADO, CIUDAD, CALLE
Y tengo el archivo de Excel con los registros de los anteriores ... posiblemente 2000 filas a partir de ahora.

Usé SqlBulkCopy para importar los datos a una tabla temporal, permite nombrar la tabla IMPORT.

Y escribí un activador para insertar en la tabla IMPORT que obtiene el registro insertado y divide el país, el estado, la ciudad, la calle y luego los inserta en la tabla correspondiente.

En este desencadenador, tengo que hacer una verificación condicional, como, si el nombre de PAÍS ya está presente, luego devuelve el ID de país; de lo contrario, insértelo y obtenga el nuevo ID de país.

Lo anterior funciona si el archivo de Excel tiene una sola fila. Una vez que coloqué el Excel original para la importación, descubrí que la siguiente declaración en el activador falla "seleccionar país desde INSERTADO" porque sqlbulkcopy hace que INSERTADO tenga más de un registro.

Estructura de la tabla

PAÍS

  • ID de país
  • Nombre del país

ESTADO

  • State_ID
  • ID de país
  • Nombre del Estado

CIUDAD

  • Ciudad_ID
  • State_ID
  • ID de país
  • Nombre de la ciudad

CALLE

  • Street_ID
  • Ciudad_ID
  • State_ID
  • ID de país
  • Nombre de la calle

IMPORTAR

  • Nombre del país
  • Nombre del Estado
  • Nombre de la ciudad
  • Nombre de la calle

Entonces, ¿puedo tener una instrucción de bucle en el desencadenador que se repita en todos los registros en INSERTADO?

¿O cómo abordar esto de la mejor manera?

NOTA: como ya lo están utilizando, no tengo control sobre la estructura de la tabla y sus relaciones.

Gracias por adelantado.

Respuesta aceptada

Sus primeros problemas son que nunca debe considerar recorrer un conjunto de registros como primera opción. Casi siempre es la elección equivocada, ya que está aquí. El siguiente problema es que los desencadenadores procesan todo el conjunto de registros, no uno por uno y, según su descripción, apuesto a que lo escribió, suponiendo que procesaría un registro a la vez. Necesitas un proceso basado en conjuntos.

Es probable que necesite algo como esto en su desencadenante que insertaría todos los países en inserciones que aún no están en la tabla de países (esto supone que country_Id es una columna de identidad entera):

Insert country (country_name)
select country_name 
from inserted i
where not exists 
  (select * from country c 
   where c.country_name = i.country_name)

También puede utilizar un proceso almacenado en lugar de un desencadenante para insertarlo en las tablas reales desde la tabla de estadificación.


Respuesta popular

¡ Nunca pondría una tarea tan intensiva de procesamiento en un disparador en una tabla usada para carga masiva! Y nunca jamás empezar a poner bucles como cursores y cosas por el estilo en un gatillo - un disparador debe ser pequeño, ligero y robusto - sólo un INSERT rápida en una tabla de auditoría o algo - pero no debe hacer trabajo pesado!

Lo que debes hacer es esto:

  • use SqlBulkLoad para obtener sus datos en esa tabla de preparación lo más rápido posible, sin desencadenantes ni nada
  • luego, en función de esa tabla de etapas, realice el posprocesamiento necesario dividiendo los valores de las columnas y cosas así

De lo contrario, estás SqlBulkLoad totalmente cualquier beneficio que SqlBulkLoad tenga.

Y para realizar este procesamiento posterior (como determinar Country_ID para un Country determinado), no necesita cursores ni ninguno de esos bits malvados, solo use declaraciones UPDATE estándar, comunes en su tabla, eso es todo lo que necesita necesitar.



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é