30

I have a stored procedure that needs to insert into three different tables, but I need to get the ID generated from the one input and use that to insert into the next table. I'm familiar with the INSERT-OUTPUT construct, but I'm not sure how to go about using it in this particular case.

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

But I get the following errors:

The multi-part identifier "g.GUID" could not be bound.

The multi-part identifier "c.GUID" could not be bound.

I'll get similar errors if I use s.GUID instead. Is it possible to do a kind of join in the OUTPUT clause?

2
  • 3
    You're getting the error because you can't use anything other than the INSERTED or DELETED references on inserts (which means you can only use INSERTED, of course). With updates and deletes, you can reference the other tables used in your query. The merge option below should work so long as you're using SQL Server 2008 or higher. The only way I've found to do it otherwise is to find an unused column on the table I'm inserting into and put the value (in your case, the guid) into that column, then go back and pull out the column later (and update it back to null so it doesn't stay there). Commented Mar 7, 2013 at 21:45
  • try this inserted.GUID Commented Nov 17, 2014 at 16:05

1 Answer 1

41

I'm not sure if that is the best option, but it seems you can do the trick using 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
Sign up to request clarification or add additional context in comments.

4 Comments

Please forgive my ignorance. I've never used MERGE or even seen it used in the wild. Could you explain this code a bit?
That's an excellent article. But, the short answer to your question is that MERGE allows one to combine any combination of INSERT, UPDATE and DELETE in a single statement (this code forces an INSERT). MERGE is useful for you here because it allows using columns from different tables in the OUTPUT clause, while INSERT doesn't.
@GilM and a question about it here
@MikaelEriksson Or a newer link to Dr. OUTPUT or: How I Learned to Stop Worrying and Love the MERGE if the other one doesn't work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.