I wonder which is better practice when I need to return the primary key value of a newly inserted record from a SQL stored procedure. Consider the following implementations:
As Return Value
CREATE PROCEDURE [CreateRecord] ( @value NVARCHAR(128) )
AS
BEGIN
INSERT [Records] ( [Value] ) VALUES ( @value );
RETURN SCOPE_IDENTITY();
END
Obviously this only works for INT
keys, but it takes advantage of pre-existing functionality. Also, only works when inserting a single record. I have seen this done in few places, but I generally don't like it.
As Output Parameter
CREATE PROCEDURE [CreateRecord] ( @value NVARCHAR(128), @id INT = NULL OUTPUT )
AS
BEGIN
INSERT [Records] ( [Value] ) VALUES ( @value );
SET @id = SCOPE_IDENTITY();
END
Works for any type of key, including multi-column keys, but still only works when inserting a single record. This is my preferred method unless I absolutely have to insert more than one record at a time.
As XML Output Parameter
CREATE PROCEDURE [CreateRecord] ( @value NVARCHAR(128), @xmldata XML = NULL OUTPUT )
AS
BEGIN
DECLARE @inserted TABLE ( Id INT );
INSERT [Records] ( [Value] )
OUTPUT [inserted].[Id]
INTO @inserted ( [Id] )
VALUES ( @value );
SET @xmldata = (SELECT [Id] FROM @inserted FOR XML AUTO);
END
This is similar to the previous solution, but allows multiple records to be returned. Trying to parse the output would be a huge pain, but I suppose this would be suitable for some applications. For example, if a stored procedure can insert into several different tables, a single output parameter can describe all the inserted records.
As Result Set
CREATE PROCEDURE [CreateRecord] ( @value NVARCHAR(128) )
AS
BEGIN
DECLARE @inserted TABLE ( Id INT );
INSERT [Records] ( [Value] )
OUTPUT [inserted].[Id]
INTO @inserted ( [Id] )
VALUES ( @value );
SELECT * FROM @inserted;
END
Superficially, this may be appealing, especially if your calling this SP from ADO, since getting the result set from the command is very straight forward. To use this SP from SQL, however, you have to write an INSERT-EXEC
script, which is somewhat inelegant, in my opinion (but still a lot better than parsing XML).
Perhaps there are other methods that I'm not even aware of. What is the best method of returning the newly inserted key value from this kind of stored procedure? Are there any guidelines for deciding which is the best method?