views:

31

answers:

4

I have 2 tables- master and detail table. Master Table has ID column which is Primary key and Auto Id. I have wrtten an SP to insert records into both tables. In this SP, when a record id inserted in master table, current_ident is fetched and stored in a variable which is then passed to detail table insert the detail records. This is working absolutely fine when transactions are done one by one. But when multiple users concurrently create the transactions sometimes the detail records of one transaction are getting inserted for some other transaction which is a dangerous thing. Please help me to resolve this issue.

+2  A: 

I would use the SCOPE_IDENTITY() in this case.

http://msdn.microsoft.com/en-us/library/ms190315.aspx

Yves M.
This is the correct one. It has worked. Many thanks for the timely help
Geeta K.
A: 

Have you got your transactions setup correctly? Your SP should look something like this

BEGIN TRAN

DECLARE @id INT

INSERT INTO Master (x, y , z) ...
SELECT @id = @@identity

INSERT INTO Child (id, foo, bar) VALUES (@id, ...

COMMIT TRAN
RETURN 0

:Err
ROLLBACK
RETURN 1

Assuming this is correct you need to check the default isolation level of your server, and the isolation level of the connections executing your stored procedure, but its more likely a bug in the SP

Jon Freedman
Not `@@identity` that can return incorrect results if a trigger on the table does an insert to another table for example.
Martin Smith
+2  A: 

use SCOPE_IDENTITY() (Returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch.) instead of @@IDENTITY.

igor
Igor, Many thanks for this information. I have used SCOPE_IDENTITY() in place of Ident_Current and deployed it on live server. I will have to wait for a weeks time to know whether this issue has been resolved. we get this error very rarely that too only on live server.Many thanks for your input.
Geeta K.
@Geeta K. welcome!
igor
A: 

I would just use SCOPE_IDENTITY() for this.

In SQL Server 2008 (looking at the question title not the tag) this is possible without but the syntax is pretty clunky.

USE tempdb

CREATE TABLE [master] (id INT IDENTITY (10,1) PRIMARY KEY,
                       othercol VARCHAR(10));

CREATE TABLE details (id INT IDENTITY PRIMARY KEY, 
                      masterid INT FOREIGN KEY REFERENCES [master](id),
                      detailscol VARCHAR(10));

SET XACT_ABORT ON
BEGIN TRAN     

DECLARE @details VARCHAR(10) = 'details row'
DECLARE @master VARCHAR(10) = 'master row'

INSERT INTO details
                      (masterid, detailscol)
  EXEC sp_executesql
    @stmt = N'
     INSERT INTO master
                      (othercol)
               OUTPUT INSERTED.id AS master_id, @details VALUES (@master)',
    @params = N'@details varchar(10), @master varchar(10)',
    @details = @details,
    @master = @master;


 SELECT * FROM [master]
 SELECT * FROM [details]
 COMMIT
Martin Smith