2013-03-07 8 views
22

Ho una procedura memorizzata che deve essere inserita in tre tabelle diverse, ma ho bisogno di ottenere l'ID generato da un input e usarlo per inserirlo nella tabella successiva. Ho familiarità con il costrutto , ma non sono sicuro di come utilizzarlo in questo caso particolare.INSERT-OUTPUT con colonna da altra tabella

DECLARE @guids TABLE ([GUID] UNIQUEIDENTIFIER); 
DECLARE @contacts TABLE ([ContactID] INT, [GUID] UNIQUEIDENTIFIER); 
DECLARE @mappings TABLE ([TargetID] INT, [GUID] UNIQUEIDENTIFIER); 

INSERT @guids ([GUID]) ... 

INSERT [Contacts] ([FirstName], [LastName], [ModifiedDate]) 
OUTPUT [inserted].[ContactID], g.[GUID] 
INTO @contacts 
SELECT [First_Name], [Last_Name], GETDATE() 
FROM [SourceTable] s 
JOIN @guids g ON s.[GUID] = g.[GUID] 

INSERT [TargetTable] ([ContactID], [License], [CreatedDate], [ModifiedDate]) 
OUTPUT [inserted].[TargetID], c.[GUID] 
INTO @mappings 
SELECT c.[ContactID], [License], [CreatedDate], [CreatedDate] 
FROM [SourceTable] s 
JOIN @contacts c ON s.[GUID] = c.[GUID] 

INSERT [Mappings] ([TargetID], [SourceGUID]) 
SELECT [TargetID], [GUID] 
FROM @mappings 

ma ottengo i seguenti errori:

L'identificatore in più parti "g.GUID" non poteva essere legato.

L'identificatore di più parti "c.GUID" non può essere associato.

Avrò errori simili se uso s.GUID invece. È possibile fare un tipo di adesione nella clausola OUTPUT?

+1

Stai diventando l'errore perché non è possibile utilizzare altro che l'INSERTED o DELETED riferimenti su inserti (il che significa che puoi solo usare INSERTED, ovviamente). Con gli aggiornamenti e le eliminazioni, è possibile fare riferimento alle altre tabelle utilizzate nella query. L'opzione di unione sotto dovrebbe funzionare fino a quando si utilizza SQL Server 2008 o versioni successive. L'unico modo in cui ho trovato di farlo altrimenti è trovare una colonna inutilizzata sul tavolo in cui sto inserendo e inserire il valore (nel tuo caso, il guid) in quella colonna, quindi tornare indietro e tirare fuori la colonna più tardi (e aggiornarlo di nuovo in modo da non rimanere lì). –

+0

prova questo inserito.GUID – user123456

risposta

30

Non sono sicuro se questa è l'opzione migliore, ma sembra che si può fare il trucco utilizzando MERGE:

MERGE [Contacts] trgt 
USING 
( 
    SELECT [First_Name], [Last_Name], g.[GUID] as [GUID] 
    FROM [SourceTable] s 
    JOIN @guids g ON s.[GUID] = g.[GUID] 
)src ON (1=0) 
WHEN NOT MATCHED THEN INSERT ([FirstName], [LastName], [ModifiedDate]) 
VALUES (src.[First_Name],src.[Last_Name], GETDATE()) 
OUTPUT [inserted].[ContactID], src.[GUID] 
INTO @contacts 
+0

Per favore perdona la mia ignoranza. Non ho mai usato 'MERGE' o addirittura l'ho visto usato in natura. Potresti spiegare questo codice un po '? –

+4

[Dr. OUTPUT o: Come ho imparato a smettere di preoccuparmi e ad amare MERGE] (http://sqlblog.com/blogs/adam_machanic/archive/2009/08/24/dr-output-or-how-i-learned-to-stop -worrying-and-love-the-merge.aspx) –

+4

Questo è un articolo eccellente. Ma la risposta breve alla tua domanda è che MERGE consente di combinare qualsiasi combinazione di INSERT, UPDATE e DELETE in una singola istruzione (questo codice forza un INSERT). MERGE è utile qui perché consente di utilizzare colonne da tabelle diverse nella clausola OUTPUT, mentre INSERT no. – GilM

Problemi correlati