devon-lad
asked on
Problems getting @@IDENTITY and SCOPE_IDENTITY after INSERT
I've got an ASP page that needs to INSERT a record into a table and then use the new record ID to INSERT a record into another table.
Have used the following, which has worked just fine in the past
INSERT INTO MyTable (.......) VALUES (....)
SELECT @@IDENTITY AS NewRecordID
But NewRecordID is null after the record has been inserted.
Read somewhere that I should be doing the following:
SET NOCOUNT ON
INSERT INTO MyTable (.......) VALUES (....)
SELECT @@IDENTITY AS NewRecordID
SET NOCOUNT OFF
This appeared to run correctly. However, having looked at MyTable, I've found that the record has been inserted twice.
If I remove the SET NOCOUNT, it is only inserted once, but the ID is null.
Have tried both the above using SCOPE_IDENTITY() instead - but same results.
What's going on here then?
I'm using an ODBC connection to SQL 2000. No triggers.
Need to resolve this quickly - so max points.
Have used the following, which has worked just fine in the past
INSERT INTO MyTable (.......) VALUES (....)
SELECT @@IDENTITY AS NewRecordID
But NewRecordID is null after the record has been inserted.
Read somewhere that I should be doing the following:
SET NOCOUNT ON
INSERT INTO MyTable (.......) VALUES (....)
SELECT @@IDENTITY AS NewRecordID
SET NOCOUNT OFF
This appeared to run correctly. However, having looked at MyTable, I've found that the record has been inserted twice.
If I remove the SET NOCOUNT, it is only inserted once, but the ID is null.
Have tried both the above using SCOPE_IDENTITY() instead - but same results.
What's going on here then?
I'm using an ODBC connection to SQL 2000. No triggers.
Need to resolve this quickly - so max points.
ASKER
Well, I'm assuming it is the SQL because if I remove the SET NOCOUNT from the SQL statement - not making any changes to the code - the INSERT works fine and only inserts 1 record.
and I can be sure that with only that sql by itself, it's not possible.
so, please, show use the relevant asp code.
so, please, show use the relevant asp code.
side note:
as from sql 2000, forget @@IDENTITY.
only use SCOPE_IDENTITY()
as from sql 2000, forget @@IDENTITY.
only use SCOPE_IDENTITY()
ASKER
The following If block is part of a loop, but I have inserted a simply Response.Write in the block to double check it's only being processed once.
If I use the following code, the record is inserted twice and iOrderID is set to the id of the second record.
If iOrderID = 0 Then
sTimeStamp = Date & " " & Time
sql = "SET NOCOUNT ON;
sql = sql & "INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(" & iSID & ",'" & sTimeStamp & "','" & Request("txtEmail") & "');"
sql = sql & "SELECT SCOPE_IDENTITY() AS NewOrderId;"
sql = sql & "SET NOCOUNT OFF"
OpenRS(sql)
iOrderID = Rs("NewOrderId")
CloseRS()
End If
If I use the following code, the record is inserted once, but iOrderID is null
If iOrderID = 0 Then
sTimeStamp = Date & " " & Time
sql = "INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(" & iSID & ",'" & sTimeStamp & "','" & Request("txtEmail") & "');"
sql = sql & "SELECT SCOPE_IDENTITY() AS NewOrderId;"
OpenRS(sql)
OrderID = Rs("NewOrderId")
CloseRS()
End If
OpenRS is a function as follows
Dim Rs
Function OpenRS(sql)
Err.Clear
RsIsEmpty = False
On Error Resume Next
Set Rs = Server.CreateObject("ADODB .Recordset ")
Rs.Open sql, DbConnection, adOpenStatic
CheckForError()
If Rs.BOF And Rs.EOF Then
RsIsEmpty = True
Else
Rs.MoveFirst
End If
End Function
If I use the following code, the record is inserted twice and iOrderID is set to the id of the second record.
If iOrderID = 0 Then
sTimeStamp = Date & " " & Time
sql = "SET NOCOUNT ON;
sql = sql & "INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(" & iSID & ",'" & sTimeStamp & "','" & Request("txtEmail") & "');"
sql = sql & "SELECT SCOPE_IDENTITY() AS NewOrderId;"
sql = sql & "SET NOCOUNT OFF"
OpenRS(sql)
iOrderID = Rs("NewOrderId")
CloseRS()
End If
If I use the following code, the record is inserted once, but iOrderID is null
If iOrderID = 0 Then
sTimeStamp = Date & " " & Time
sql = "INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(" & iSID & ",'" & sTimeStamp & "','" & Request("txtEmail") & "');"
sql = sql & "SELECT SCOPE_IDENTITY() AS NewOrderId;"
OpenRS(sql)
OrderID = Rs("NewOrderId")
CloseRS()
End If
OpenRS is a function as follows
Dim Rs
Function OpenRS(sql)
Err.Clear
RsIsEmpty = False
On Error Resume Next
Set Rs = Server.CreateObject("ADODB
Rs.Open sql, DbConnection, adOpenStatic
CheckForError()
If Rs.BOF And Rs.EOF Then
RsIsEmpty = True
Else
Rs.MoveFirst
End If
End Function
thanks.
ok, take the response.write of the genrated SQL, and run it in Query Analyser.
does it insert 1 or 2 rows?
if it inserts 1 rows, your code/page is called twice, even if you only see the response.write once.
if it inserts 2 rows, there MUST be some trigger on the table.
ok, take the response.write of the genrated SQL, and run it in Query Analyser.
does it insert 1 or 2 rows?
if it inserts 1 rows, your code/page is called twice, even if you only see the response.write once.
if it inserts 2 rows, there MUST be some trigger on the table.
ASKER
Only inserts once!?
I can't see how the page is being called twice.
Firstly from the user side - the Submit button is disabled after clicking, so the form data is only being submitted once.
Secondly, if I use the code without the SET NOCOUNT, the record is only inserted once. So the page is obviously not called twice.
Ah...wait a minute. When I remove the SET NOCOUNT, although it only inserts one record - the page doesn't finish processing because of a later error due to iOrderID being null. Maybe if it continued it would actually end up inserting two records as well.
Let me just check
I can't see how the page is being called twice.
Firstly from the user side - the Submit button is disabled after clicking, so the form data is only being submitted once.
Secondly, if I use the code without the SET NOCOUNT, the record is only inserted once. So the page is obviously not called twice.
Ah...wait a minute. When I remove the SET NOCOUNT, although it only inserts one record - the page doesn't finish processing because of a later error due to iOrderID being null. Maybe if it continued it would actually end up inserting two records as well.
Let me just check
ASKER
I have created a new page with only the folowing lines of code in it
OpenDB()
sql = "SET NOCOUNT ON;INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(9,'" & Date & " " & Time & "','someone@somewhere.com' );SELECT SCOPE_IDENTITY() AS NewOrderId"
' sql = "INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(9,'" & Date & " " & Time & "','someone@somewhere.com' )"
OpenRS(sql)
If I run it with the second sql statement commented out, it inserts two rows. If I run it with the first line commented out, it inserts one row.
OpenDB()
sql = "SET NOCOUNT ON;INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(9,'" & Date & " " & Time & "','someone@somewhere.com'
' sql = "INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(9,'" & Date & " " & Time & "','someone@somewhere.com'
OpenRS(sql)
If I run it with the second sql statement commented out, it inserts two rows. If I run it with the first line commented out, it inserts one row.
ASKER
Sorry, that should be, when I run it with the first sql statement commented out - not the first line.
ok, let's see:
* what is the exact version / sp of your sql server? ( select @@version )
* what is the full table structure ?
* can you try on another test table, with 0 rows in it?
can you show the contents of the table after the "single insert request, 2 rows generated? "
* what is the exact version / sp of your sql server? ( select @@version )
* what is the full table structure ?
* can you try on another test table, with 0 rows in it?
can you show the contents of the table after the "single insert request, 2 rows generated? "
ASKER
Version is
Microsoft SQL Server 2000 - 8.00.2039 (Intel X86) May 3 2005 23:18:38 Copyright (c) 1988-2003 Microsoft Corporation Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
The table is very simple
Order_Id int 4 - Primary key, Identity, auto-increment
Order_Date datetime 8
Order_Site_Id int 4 - Foreign key
Order_Email varchar 50
Created a test table - same structure - but didn't link the foreign key.
Ran the test page for the single insert and got the following
Test_Id Test_Date Test_Site_Id Test_Email
1 03/10/2007 13:34:43 9 someone@someplace.com
2 03/10/2007 13:34:43 9 someone@someplace.com
Microsoft SQL Server 2000 - 8.00.2039 (Intel X86) May 3 2005 23:18:38 Copyright (c) 1988-2003 Microsoft Corporation Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
The table is very simple
Order_Id int 4 - Primary key, Identity, auto-increment
Order_Date datetime 8
Order_Site_Id int 4 - Foreign key
Order_Email varchar 50
Created a test table - same structure - but didn't link the foreign key.
Ran the test page for the single insert and got the following
Test_Id Test_Date Test_Site_Id Test_Email
1 03/10/2007 13:34:43 9 someone@someplace.com
2 03/10/2007 13:34:43 9 someone@someplace.com
ASKER
Changed the SQL to insert without the SET NOCOUNT or the SELECT SCOPE_IDENTITY() and it has created one row in the table.
what is the connection string?
can you try this (remove the ; from the sql)
sql = "SET NOCOUNT ON INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(9,'" & Date & " " & Time & "','someone@somewhere.com' ) SELECT SCOPE_IDENTITY() AS NewOrderId"
can you try this (remove the ; from the sql)
sql = "SET NOCOUNT ON INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email) VALUES(9,'" & Date & " " & Time & "','someone@somewhere.com'
ASKER
Here's the OpenDB() function
Function OpenDB()
On Error Resume Next
sConnString = "DSN=tm_order;UID=dbUserNa me;PWD=dbP assword"
Set dbOrder = Server.CreateObject("ADODB .Connectio n")
dbOrder.Open(sConnString)
CheckForError(sConnString)
Set cmdTemp = Server.CreateObject("ADODB .Command")
cmdTemp.CommandType = 1
Set cmdTemp.ActiveConnection = dbOrder
End Function
Having looked at this now, not quite sure what the Set cmdTemp lines are doing - wrote this code years ago - don't do alot programming these days - maybe they are superfluous?
Will try the sql string without the semi-colons...
Function OpenDB()
On Error Resume Next
sConnString = "DSN=tm_order;UID=dbUserNa
Set dbOrder = Server.CreateObject("ADODB
dbOrder.Open(sConnString)
CheckForError(sConnString)
Set cmdTemp = Server.CreateObject("ADODB
cmdTemp.CommandType = 1
Set cmdTemp.ActiveConnection = dbOrder
End Function
Having looked at this now, not quite sure what the Set cmdTemp lines are doing - wrote this code years ago - don't do alot programming these days - maybe they are superfluous?
Will try the sql string without the semi-colons...
ASKER
Removing the semi-colons from the sql string does not have any effect - still get the same results.
Here as I understand you are using multiple resultset. I guess you need to call like this
OpenRS(sql)
Set RS = RS .NextRecordset()
OrderID = Rs("NewOrderId")
Also use SET NOCOUNT ON and OFF
Have a nice day
OpenRS(sql)
Set RS = RS .NextRecordset()
OrderID = Rs("NewOrderId")
Also use SET NOCOUNT ON and OFF
Have a nice day
@assyst:
please note that using the "proposed answer" should NOT be used (yet), unless you are like at least 99% sure of your answer.
which cannot be the case, as you used "I guess".
also, you have not read the question and the comments carefully enough, otherwise you would not have posted that code ...
@devon-lad:
what driver does the DSN use?
please note that using the "proposed answer" should NOT be used (yet), unless you are like at least 99% sure of your answer.
which cannot be the case, as you used "I guess".
also, you have not read the question and the comments carefully enough, otherwise you would not have posted that code ...
@devon-lad:
what driver does the DSN use?
ASKER
SQL Server driver setup as a System DSN.
Is that what you mean?
Is that what you mean?
yes.
ok, let's check this:
create a procedure in sql server database:
CREATE PROCEDURE dbo.test_insert
( @date_time varchar(100)
, @email varchar(100)
)
AS
SET NOCOUNT ON
INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email)
VALUES(9, @date_time, @email)
SELECT SCOPE_IDENTITY() AS NewOrderId
GO
and change your asp code to :
sql = "EXEC dbo.test_insert '" & Date & " " & Time & "','someone@somewhere.com' "
ok, let's check this:
create a procedure in sql server database:
CREATE PROCEDURE dbo.test_insert
( @date_time varchar(100)
, @email varchar(100)
)
AS
SET NOCOUNT ON
INSERT INTO ItemOrder (Order_Site_Id, Order_Date, Order_Email)
VALUES(9, @date_time, @email)
SELECT SCOPE_IDENTITY() AS NewOrderId
GO
and change your asp code to :
sql = "EXEC dbo.test_insert '" & Date & " " & Time & "','someone@somewhere.com'
ASKER
Ok, done that.
It gives the same results - two rows inserted.
It gives the same results - two rows inserted.
next idea:
run the query profiler to trace what queries are being submitted to the database.
I must assume that the procedure / query IS submitted twice...
run the query profiler to trace what queries are being submitted to the database.
I must assume that the procedure / query IS submitted twice...
ASKER
You're right - it is submitted twice.
Yet if I change sql to do a straight INSERT without the SET NOCOUNT and SCOPE_IDENTITY it's only submitted once.
Yet if I change sql to do a straight INSERT without the SET NOCOUNT and SCOPE_IDENTITY it's only submitted once.
so it MUST be the code, somehow...
can you show me:
CheckForError()
can you show me:
CheckForError()
ASKER
I've commented out CheckForError() in the OpenRS() function - same result.
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
It worked - only one row inserted.
Have replaced stored procedure with original code - this works as well.
But why does it work where RS.Open doesn't?
Have replaced stored procedure with original code - this works as well.
But why does it work where RS.Open doesn't?
honestly, I have no idea about the why...
started searching around (even in my head/memory), but to no avail...
started searching around (even in my head/memory), but to no avail...
ASKER
Why do you call it the "brute force" method?
Are there issues I should be aware of?
Are there issues I should be aware of?
>Why do you call it the "brute force" method?
>Are there issues I should be aware of?
"brute force" to try to get around the recordset.open, that might run the sql twice (although that was not what I thought...)
not in this context. it simply opens a forward-only, read-only recordset
>Are there issues I should be aware of?
"brute force" to try to get around the recordset.open, that might run the sql twice (although that was not what I thought...)
not in this context. it simply opens a forward-only, read-only recordset
This is really an interesting topic and I do really appreciate AngelIII's dedication in getting it solved. I regret putting my comments as proposed solution. All I was looking is to HELP.
You are an expert with good attitude.
You are an expert with good attitude.
ASKER
All seems to work fine now - thanks for your efforts angelIII - a rather strange problem, definitely one for the KB.
can you show the code that you use to run this sql?
the sql, by itself, will NOT insert the record twice!