A common problem in writing stored procedures arises when you need to insert one record into table T1 and one or more records into table T2, with the latter containing the PK of the row you just added to T1. Typically, this situation arises when you're doing batch inserts into a parent and child table.
To handle this situation, SQL Server provides the variable @@Identity. Following the insert into the parent table, you grab the value of its primary key from @@Identity.
This seems straightforward, but there is a subtle issue that could cause you problems. Before I show you how to work around the problem, let's look at the problem itself. Run the code in Listing A in Query Analyzer against some test database.
After creating the objects, you insert a row into the parent table, and save its key into a variable, and then another row into the child table. Now run these commands:
select * from identity_problem_a
select * from identity_problem_b
The results will look something like this:
1000 This is some text
1 1 This is still some text
The result is a bit surprising. Note the value returned in the second column from identity_problem_b. It's supposed to be 1000, the primary key that was just inserted into the identity_problem_a table. So why is the value 1 rather than 1000?
The reason is that the @@Identity value has no concept of scope in the sense that most programming languages do. Thus, even though the code presented grabs the Identity value immediately after performing the insert into the parent table, the trigger on the parent table performs another insert, into a different table with a different identity seed. So by the time you test @@Identity, its value has already changed and the old value is gone.
To address this problem, SQL Server 2000 adds the new Scope_Identity() function, which as its name implies, "remembers" the scope or context. Thus, the identity value inside the trigger is local to the trigger.
To fix the problem, we only need to change one line of the original code. You need to change this line:
SELECT @pk = @@IDENTITY
to this code:
SELECT @pk = Scope_Identity()
Now the code will perform as intended.
TechRepublic's free SQL Server newsletter, delivered each Tuesday, contains hands-on tips that will help you become more adept with this powerful relational database management system. Automatically subscribe today!