web-dev-qa-db-fra.com

Insérer avec OUTPUT corrélé à la sous-table de requête

Je modifie la structure d'une base de données. Le contenu de plusieurs colonnes du tableau FinancialInstitution doit être transféré dans le tableau Person. FinancialInstitution est lié à la personne avec une clé étrangère. Chaque institution financière a besoin de l'ID de sa personne correspondante. Ainsi, pour chaque nouvelle ligne insérée dans Person, l'id de cette nouvelle ligne (IDENTITY) doit être recopié dans la ligne correspondante de FinancialInstitution.

La façon évidente de le faire est un code T-SQL itératif. Mais je voudrais savoir s'il est possible de le faire uniquement avec des opérations basées sur des ensembles.

J'ai imaginé que le niveau interne d'une telle demande serait quelque chose comme:

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;

Malheureusement, il semble que OUTPUT ne puisse pas être corrélé de cette façon ...

22
Yugo Amaryl

Je suppose que vous pourriez (ab) utiliser MERGE pour cela. Créez d'abord une table (temporaire):

CREATE TABLE tempIDs
( PersonId INT, 
  FinancialInstitutionId INT
) ;

Puis MERGE dans Person (au lieu de INSERT), vous pouvez donc utiliser les colonnes des tables impliquées dans la clause OUTPUT:

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 ;

Utilisez ensuite la table temporaire pour UPDATE FinancialInstitution:

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

Testez à: SQL-Fiddle

18
ypercubeᵀᴹ