Insertar con SALIDA correlacionado con la tabla de subconsulta

22

Estoy modificando la estructura de una base de datos. El contenido de varias columnas de la tabla FinancialInstitution debe transferirse a la tabla Persona . La institución financiera está vinculada a la persona con una clave externa. Cada institución financiera necesita la identificación de su persona correspondiente. Por lo tanto, para cada nueva línea insertada en Persona, la identificación de esta nueva línea (IDENTIDAD) debe copiarse nuevamente en la línea correspondiente de FinancialInstitution.

La forma obvia de hacer esto es un código T-SQL iterativo. Pero estoy interesado en saber si es posible hacerlo solo con operaciones basadas en conjuntos.

Imaginé que el nivel interno de tal solicitud sería algo como:

INSERT INTO Person (Street1, Number1, City1, State1, PostCode1, CountryId1, WorkDirectPhone1, Fax1, Email1)
OUTPUT inserted.Id, FinancialInstitution.Id
SELECT Id, Street, Number, City, [State], PostCode, CountryId, PhoneNumber, Fax, Email
FROM FinancialInstitution;

Desafortunadamente, parece que OUTPUT no puede correlacionarse de esa manera ...

Yugo Amaryl
fuente
¿Desea insertar filas en la tabla Person? ¿O actualizar las existentes? ¿O quieres insertar en Persony luego UPDATE FinancialInstitution?
ypercubeᵀᴹ
Su consulta solo está actualizando la tabla Persona. Puede capturar el ID insertado, pero no el ID de institución financiera, a menos que lo use en la parte de inserción. La forma en que se encuentra su consulta, si elimina la cláusula OUTPUT, obtendrá un error porque el número de columnas en su instrucción INSERT no coincide con la instrucción SELECT.
datagod
ypercube: deseo insertar en persona y luego actualizar FinancialInstitution con el ID de la nueva fila en persona.
Yugo Amaryl
datagod: Sé que solo se actualiza, esta consulta es el nivel anidado de la solución futura. Pero ya estoy atrapado allí. Derecho, no puedo agregar Id en la selección si no lo inserto.
Yugo Amaryl

Respuestas:

18

Supongo que podrías (ab) usarlo MERGEpara esto. Primero cree una tabla (temporal):

CREATE TABLE tempIDs
( PersonId INT, 
  FinancialInstitutionId INT
) ;

Luego MERGEen Person( en lugar de INSERT), para que pueda usar columnas de las tablas involucradas en la OUTPUTcláusula:

MERGE INTO Person 
USING FinancialInstitution AS fi
  ON 1 = 0
WHEN NOT MATCHED THEN
  INSERT (Street1, Number1, City1, ...)
  VALUES (fi.Street, fi.Number, fi.City, ...)
OUTPUT inserted.Id, fi.Id
  INTO tempIDs ;

Luego use la tabla temporal para UPDATE FinancialInstitution:

UPDATE fi
SET fi.PersonId = t.PersonId
FROM FinancialInstitution AS fi
  JOIN tempIDs AS t
    ON fi.Id = t.FinancialInstitutionId ; 

Prueba en: SQL-Fiddle

ypercubeᵀᴹ
fuente