Wstaw z OUTPUT skorelowanym z tabelą zapytań podrzędnych

22

Zmieniam strukturę bazy danych. Zawartość kilku kolumn tabeli FinancialInstitution należy przenieść do tabeli Osoba . FinancialInstitution jest powiązany z osobą posiadającą klucz obcy. Każda instytucja finansowa potrzebuje identyfikatora odpowiedniej osoby. Tak więc, dla każdego nowego wiersza wstawionego w Person, identyfikator tego nowego wiersza (TOŻSAMOŚĆ) musi zostać skopiowany z powrotem do odpowiedniego wiersza FinancialInstitution.

Oczywistym sposobem na to jest iteracyjny kod T-SQL. Ale chcę wiedzieć, czy można to zrobić tylko za pomocą operacji opartych na zestawie.

Wyobrażałem sobie, że wewnętrzny poziom takiego żądania mógłby wyglądać następująco:

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;

Niestety wydaje się, że OUTPUT nie może korelować w ten sposób ...

Yugo Amaryl
źródło
Czy chcesz wstawić wiersze do tabeli Person? Lub zaktualizować istniejące? Albo chcesz wstawić Person, a następnie UPDATE FinancialInstitution?
ypercubeᵀᴹ
Twoje zapytanie tylko aktualizuje tabelę Osoby. Możesz przechwycić insert.ID, ale nie FinancialInstitution.ID, chyba że użyjesz go w części insert. Sposób, w jaki znajduje się zapytanie, jeśli usuniesz klauzulę OUTPUT, otrzymasz błąd, ponieważ liczba kolumn w instrukcji INSERT jest niezgodna z instrukcją SELECT.
datagod
ypercube: Chcę wstawić do osoby, a następnie zaktualizować FinancialInstitution o Id nowego wiersza w Person.
Yugo Amaryl
datagod: Wiem, że to jedyna aktualizacja, to zapytanie jest zagnieżdżonym poziomem przyszłego rozwiązania. Ale już tam utknąłem. Nie mogę dodać Id do zaznaczenia, jeśli go nie wstawię.
Yugo Amaryl
1
@YugoAmaryl, możesz spróbować zastosować ten przykład, używając klauzuli WYJŚCIE do przechwytywania wartości tożsamości na
wstawkach wielorzędowych

Odpowiedzi:

18

Myślę, że możesz (ab) użyć MERGEdo tego. Najpierw utwórz (tymczasową) tabelę:

CREATE TABLE tempIDs
( PersonId INT, 
  FinancialInstitutionId INT
) ;

Następnie MERGEdo Person(zamiast INSERT), aby można było użyć kolumn tabel objętych OUTPUTklauzulą:

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 ;

Następnie użyj tabeli tymczasowej, aby UPDATE FinancialInstitution:

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

Test na: SQL-Fiddle

ypercubeᵀᴹ
źródło