I have a complex select statement which I want to return to the application layer. At the same time I want to reuse ids from this statement. I've come to the table variable solution like this
DECLARE @Result TABLE (SortOrder int IDENTITY, Id bigint, data_columns, PRIMARY KEY (Id))
INSERT INTO @Result
SELECT Id, data_columns ...
--output to the app layer
SELECT Id, data_columns FROM @Result ORDER BY SortOrder;
--using @Result Id elsewhere
SortOrder is used to keep original order from the first select. Without it I faced a strange bug in ms sql server 2012. PRIMARY KEY (Id) is used as a hint to optimizer that Id values are unique. SortOrder does not correlate with Id.
Now I have concerns about memory and cpu overload. Does anyone have a better solution?
----- Addition: This can be an answer
DECLARE @Ids TABLE (Id bigint, PRIMARY KEY (Id));
MERGE @Ids AS ids
USING (SELECT TOP 9223372036854775807 Id, data_columns ...) AS result
ON 1=0
WHEN NOT MATCHED THEN
INSERT VALUES(result.Id)
OUTPUT result.*; --output to the app layer here
--using @Ids Id elsewhere
I can confirm it works on my sample and takes less time. But I'm still worried about order in the OUTPUT.
TOP hack explained MERGE INTO insertion order
MSDN also says
There is no guarantee that the order in which the changes are applied to the table and the order in which the rows are inserted into the output table or table variable will correspond.
Luckily I don't care about order in @Ids table. But it's important to get the same order in OUTPUT clause as it was in USING ()