Say you’ve got a two-step process where you’re:
- Inserting rows into a table that has an identity column, then
- Querying that table to figure out what identities you got
There’s a a faster way that doesn’t require hitting the table twice: the OUTPUT clause.
I’ll demonstrate it with the Badges table from the Stack Overflow database, which has an Id column that’s an identity. I’m going to find all of the Users who live in Iceland, give them a badge, and then return the list of badge IDs I just granted:
INSERT INTO dbo.Badges(Name, UserId, Date) SELECT N'Sunny Disposition', Id, GETDATE() FROM dbo.Users WHERE Location = N'Iceland'; SELECT b.Id FROM dbo.Badges b INNER JOIN dbo.Users u ON b.UserId = u.Id WHERE u.Location = N'Iceland' AND b.Name = N'Sunny Disposition' AND b.Date >= DATEADD(SS, -1, GETDATE());
This code pattern is kinda painful because:
- We lock rows twice (when we read & insert, and then again when we read back what we just did)
- We have to be careful to only fetch the rows we really just inserted – so we end up putting in all kinds of convoluted logic to work around concurrency problems
Instead, use the OUTPUT clause.
Here’s how to do it without touching the Badges & Users tables twice:
CREATE TABLE #RowsInserted (Id INT, Name NVARCHAR(40), UserId INT, [Date] DATETIME); INSERT INTO dbo.Badges(Name, UserId, Date) OUTPUT INSERTED.Id, INSERTED.Name, INSERTED.UserId, INSERTED.[Date] INTO #RowsInserted SELECT N'Sunny Disposition', Id, GETDATE() FROM dbo.Users WHERE Location = N'Iceland'; SELECT * FROM #RowsInserted;
The OUTPUT clause is kinda like the virtual INSERTED/DELETED tables: it lets you grab the output of what you’re doing and redirect it to another place. Presto, less locking, less T-SQL to manage, less guessing as to which rows were affected by your operation.
Isn’t that slick? In my own line of work, I sure don’t need to use it often, but when I do, it’s amazing.
Want to learn more tricks like this?
If you like tricks like this, you’ll love my Mastering Query Tuning class. I’ve got two upcoming sessions: December 11-13 (Fri/Sat/Sun, iCal) and January 12-14 (Tues/Weds/Thurs- iCal.)
If you’ve got a Live Class Season Pass, you can drop in on this class or any of my live online classes at any time. Just head to my current training page, check out the schedule at the bottom of the page, and grab the calendar files for the classes you’re interested in. You don’t have to register ahead of time – just drop in anytime I’m streaming.
If you don’t have one yet, I’m running a Black Friday Sale this month. Time’s running out…
- Recorded Class Season Pass
- (Fundamentals Classes)
- SQL ConstantCare®
- The Consultant Toolkit
- Normal price: $1,485
- Save $1,190 (80%)
- Live Class Season Pass
- (Including Masters Classes & Instant Replays)
- Recorded Class Season Pass
- SQL ConstantCare®
- The Consultant Toolkit
- Normal price: $5,480
- Save $4,485 (82%)
- Pester your boss just once, and save even more!
- Live Class Season Pass
- Recorded Class Season Pass
- SQL ConstantCare®
- The Consultant Toolkit
- Save $9,365 (86%)
My annual Black Friday Sale is on now! Save thousands on the best training classes in the industry.