Reputation: 37382
Let's say I have a table
my_table(id int identity(1,1) not null primary key, data varchar(100))
I want to write a procedure that inserts a new row into that table and returns id. I tried
DECLARE @new_id INT;
SELECT @new_id = id FROM
(
INSERT INTO my_table(data) OUTPUT inserted.id VALUES ('test')
) as NewVal(id)
That code doesn't work (I got "A nested INSERT, UPDATE, DELETE, or MERGE statement is not allowed in a SELECT statement that is not the immediate source of rows for an INSERT statement."). However, if I use a table variable, I can do
DECLARE @new_id INT;
DECLARE @tmp_table TABLE(int id);
INSERT INTO @tmp_table
SELECT id FROM
(
INSERT INTO my_table(data) OUTPUT inserted.id VALUES ('test')
) as NewVal(id);
// OR
INSERT INTO my_table(data) OUTPUT inserted.id INTO @tmp_table VALUES ('test') ;
SELECT @new_id = id FROM @tmp_table;
Is it possible to achieve the same functionality without using table variable ?
UPDATE
Thanks for quick responses, +1 to everyone for solution with SCOPE_IDENTITY.
That's probably my fault, I should have asked the question clearly - I do use MERGE
(an example would be much longer, so I posted INSERT
instead) , not INSERT
so SCOPE_IDENTITY doesn't really work for me.
Upvotes: 1
Views: 7613
Reputation: 138990
A bit shorter version than nesting in a insert statement is using output...into
.
declare @tmp_table table(actiontaken nvarchar(10), id int);
merge my_table
using (values ('test')) as S(data)
on 0=1
when not matched then
insert (data) values (S.data)
output $action, inserted.id into @tmp_table;
I do believe that you should use a table variable from the merge. The output may contain more than one row.
Upvotes: 5
Reputation: 3025
If you use
select @@identity
you will get the last value entered into the identity column from anywhere.
If you want the value entered into the column from the script that just ran, you should use
select SCOPE_IDENTITY()
If you just want the last value inserted into the identity column for a given table from any statement in any session, you should use
select IDENT_CURRENT('tablename')
Upvotes: 3
Reputation: 1356
select @@identity
or select SCOPE_IDENTITY()
will return the value you're looking for
Upvotes: 1
Reputation: 752
SELECT SCOPE_IDENTITY()
will get the last inserted identity value in the scope.
Upvotes: 4
Reputation: 147324
Yes, you can just return SCOPE_IDENTITY after the insert (this is safer than @@IDENTITY due to the scoping differences).
i.e.
INSERT my_table (data) VALUES ('test')
SELECT SCOPE_IDENTITY()
Upvotes: 5