Database Administrators Stack Exchange is a question and answer site for database professionals who wish to improve their database skills and learn from others in the community. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

When I insert into tables using instead of triggers, @@Identity, IDENT_CURRENT('Table') and SCOPE_IDENTITY() return null. How I can get the last identity of inserted row?

share|improve this question
There is inserted but no row inserted when an INSTEAD OF trigger triggers. – ypercubeᵀᴹ Jun 6 '12 at 7:19
Check this SO question: it may help. – gbn Jun 6 '12 at 8:58
You have to choose Select Id, .. from Inserted, here Scope_Identity, @@Identity will not work – user47587 Sep 17 '14 at 12:03
up vote 8 down vote accepted

With an INSTEAD_OF trigger it means no insert occurred yet. You cannot know the identity since it wasn't yet generated. Sneaking the value from metadata is possible (DBCC CHECKIDENT) but relying on it will not work correctly under concurrency and besides it requires elevated privileges.

INSTEAD_OF triggers are extremely seldom required and a serious code smell. Are you sure you need it? Can't you do the work with a regular AFTER trigger?

share|improve this answer
I want to control data integrity of inserted row. before save them. If data not good, I raise error proportional message. – mehdi lotfi Jun 6 '12 at 7:19
You are describing a foreign key. It should be the application responsibility to insert in the child table, not a trigger. Doing it from a trigger is bad design, and in anyway it can be done from a normal AFTER trigger. An after trigger can raise errors and cause rollback, which is the better option than an instead-of trigger. – Remus Rusanu Jun 6 '12 at 7:36
What an absurd notion - "instead of triggers are a serious code smell"? They are very useful compared to an after trigger - where, if your business rules are violated, you've done the work twice - you've inserted the rows and then you've rolled them back. An instead of trigger can prevent any of the work from happening if your business rules can't be enforced with normal DRI or other constraints. – Aaron Bertrand Jun 6 '12 at 12:09
While "instead of triggers are a serious code smell", is not a strict rule, it is based on actual possible problems it can cause in a complete system. In general, business rule breakers should never happen in the system, let alone reaching to database level. In that case, a rule validation in the trigger is only appropriate as a last defense mechanism in case there is a hole in the system. – Alireza Jun 7 '12 at 6:55
Declarative integrity is always better than a trigger. An after trigger is always better than an instead of trigger. Instead-of triggers have 'funky' behavior in a lot of situations, they are opaque to access path optimizations in DML, they make isolation levels behave erratic. Instead-of triggers scream 'I should had been an access stored procedure instead'. And I don't buy the 'do the work twice' argument at all, optimizing the exception path should not influence the design, specially at the cost of the slowing the frequent path. – Remus Rusanu Jun 7 '12 at 7:32

In your instead of trigger, you definitely can get the inserted value... but not until after you've performed the insert.

USE tempdb;

CREATE TABLE dbo.SmellThis
  id INT IDENTITY(1,1),
  name VARCHAR(32)

CREATE TRIGGER dbo.SmellThis_First
ON dbo.SmellThis

    DECLARE @ids TABLE(id INT);

      SELECT 1 FROM sys.objects AS o
        INNER JOIN inserted AS i
        ON =
    INSERT dbo.SmellThis(name)  
      OUTPUT INTO @ids
      SELECT name 
      FROM inserted;

    SELECT id FROM @ids;

INSERT dbo.SmellThis(name) SELECT 'Remus';



Now clean up:

DROP TABLE dbo.SmellThis;

As an aside, you should never, ever, ever be using @@IDENTITY or IDENT_CURRENT() anyway. And SCOPE_IDENTITY should be reserved for situations where you know only one row can ever be inserted. A common misconception with triggers is that they fire per row, like in other platforms, but in SQL Server they fire per operation - so a multi-row insert using VALUES(),(),() or INSERT...SELECT - which SCOPE_IDENTITY would you be setting to your variable?

share|improve this answer
How I save result of inserted record in variable table for use later. – mehdi lotfi Jun 6 '12 at 12:19
@mehdi can you define "later"? And can't you add columns to the table variable I've already declared above? – Aaron Bertrand Jun 6 '12 at 12:20
I should be more review. – mehdi lotfi Jun 6 '12 at 12:23
I love your table names. – Dan Esparza Sep 22 '14 at 17:44

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.