Dokonałem pewnych modyfikacji w mojej bazie danych i muszę przenieść stare dane do nowych tabel. W tym celu muszę wypełnić tabelę (ReportOptions), biorąc dane z oryginalnej tabeli (Practice), i wypełnić drugą tabelę pośrednią (PracticeReportOption).
ReportOption (ReportOptionId int PK, field1, field2...)
Practice (PracticeId int PK, field1, field2...)
PracticeReportOption (PracticeReportOptionId int PK, PracticeId int FK, ReportOptionId int FK, field1, field2...)
Wykonałem zapytanie, aby uzyskać wszystkie dane potrzebne do przejścia z Practice do ReportOptions, ale mam problem z wypełnieniem tabeli pośredniej
--Auxiliary tables
DECLARE @ReportOption TABLE (PracticeId int /*This field is not on the actual ReportOption table*/, field1, field2...)
DECLARE @PracticeReportOption TABLE (PracticeId int, ReportOptionId int, field1, field2)
--First I get all the data I need to move
INSERT INTO @ReportOption
SELECT P.practiceId, field1, field2...
FROM Practice P
--I insert it into the new table, but somehow I need to have the repation PracticeId / ReportOptionId
INSERT INTO ReportOption (field1, field2...)
OUTPUT @ReportOption.PracticeId, --> this is the field I don't know how to get
inserted.ReportOptionId
INTO @PracticeReportOption (PracticeId, ReportOptionId)
SELECT field1, field2
FROM @ReportOption
--This would insert the relationship, If I knew how to get it!
INSERT INTO @PracticeReportOption (PracticeId, ReportOptionId)
SELECT PracticeId, ReportOptionId
FROM @ReportOption
Gdybym mógł odwołać się do pola, którego nie ma w tabeli docelowej w klauzuli OUTPUT, byłoby świetnie (myślę, że nie mogę, ale nie wiem na pewno). Jakieś pomysły, jak zaspokoić moje potrzeby?
sql
sql-server
Alejandro B.
źródło
źródło
OUTPUT
klauzuli możesz zwrócić dowolną kolumnę tabeli, do której wstawiony jest wiersz . Więc nawet jeśli nie podasz wartości dla danej kolumny w swoimINSERT
wyciągu, nadal możesz określić tę kolumnę wOUTPUT
klauzuli. Nie można jednak zwracać zmiennych SQL ani kolumn z innych tabel.Odpowiedzi:
Możesz to zrobić, używając
MERGE
zamiast wstawiania:więc wymień to
z
Kluczem jest użycie predykatu, który nigdy nie będzie prawdziwy (1 = 0) w warunku wyszukiwania scalającego, więc zawsze będziesz wykonywać wstawianie, ale będziesz mieć dostęp do pól zarówno w tabeli źródłowej, jak i docelowej.
Oto cały kod, którego użyłem do przetestowania:
Więcej lektur, a źródło wszystkiego, co wiem na ten temat, znajduje się tutaj
źródło
Może ktoś, kto używa MS SQL Server 2005 lub starszego , uzna tę odpowiedź za przydatną.
MERGE będzie działać tylko dla SQL Server 2008 lub nowszego. Dla reszty znalazłem inne obejście, które da ci możliwość tworzenia tabel mapowania.
Oto jak będzie wyglądało rozwiązanie dla SQL 2005:
Główna sztuczka polega na tym, że dwukrotnie wypełniamy tabelę mapowania uporządkowanymi danymi z tabeli źródłowej i docelowej. Aby uzyskać więcej informacji, tutaj: Scalanie wstawionych danych przy użyciu OUTPUT w SQL Server 2005
źródło
Output
mojeInsert
dane wyjściowe,Table
które zawierająIdentity
wartość z celuTable
zInsert
wartością nieedytowaną (PK) ze źródłaTable
(przy okazji, więc mógłbym następnie (w innej partii) użyć tego wyjściaTable
do wypełnieniaColumn
w źródłoTable
zIdentity
wartością). Bez aMerge
, wyobrażam sobie, że musiałbym: a) rozpocząćTransaction
, b) przejść dalejIdentity
, c) wstawić do tempTable
z obliczonąIdentity
, d) ustawićIdentity_Insert
, e)Insert
do celuTable
z tempTable
, f) wyczyścićIdentity_Insert
.