Using SQL Server 2012. I want to insert unique strings into a table. I always want to return the row ID of the unique string. Now, this can be accomplished in two ways.
Which solution is the best?
This is the table in question:
CREATE TABLE [dbo].[Comment](
[CommentID] [int] IDENTITY(1,1) NOT NULL,
[Comment] [nvarchar](256) NOT NULL
CONSTRAINT [PK_Comment] PRIMARY KEY CLUSTERED([CommentID] ASC)
)
CREATE UNIQUE NONCLUSTERED INDEX [IX_Comment_Comment] ON [dbo].[Comment]
(
[Comment] ASC
)
Solution 1:
SELECT
first to check if the string exists. If it does, return its ID
. Otherwise, INSERT
a new row and return the newly created ID
.
CREATE PROCEDURE [dbo].[add_comment]
@Comment [nvarchar](256)
AS
BEGIN
SET NOCOUNT ON
DECLARE @CommentID [int]
DECLARE @TransactionCount [int]
BEGIN TRY
SET @TransactionCount = @@TRANCOUNT
IF @TransactionCount = 0
BEGIN TRANSACTION
SELECT @CommentID = [CommentID] FROM [dbo].[Comment] WHERE [Comment] = @Comment
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO [dbo].[Comment]([Comment]) VALUES (@Comment)
SET @CommentID = SCOPE_IDENTITY()
END
IF @TransactionCount = 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @TransactionCount = 0
ROLLBACK TRANSACTION
; THROW
END CATCH
RETURN @CommentID
END
Solution 2:
INSERT
first. If the insert violates the UNIQUE INDEX
, a SELECT
is issued.
CREATE PROCEDURE [dbo].[add_comment2]
@Comment [nvarchar](256)
AS
BEGIN
SET NOCOUNT ON
DECLARE @CommentID [int]
BEGIN TRY
INSERT INTO [dbo].[Comment]([Comment]) VALUES (@Comment)
SET @CommentID = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
IF @@ERROR = 2601 -- Duplicate
SELECT @CommentID = [CommentID] FROM [dbo].[Comment] WHERE [Comment] = @Comment
ELSE
THROW
END CATCH
RETURN @CommentID
END
GO
Solution 3:
Ideas? 🙂
Advertisement
Answer
In my testing I have found that it is much more efficient to check for the violation first instead of letting SQL Server try and fail, especially when the failure rate is expected to be significant (and at best they perform about the same overall, when the failure rate is low). Details here and here.
In addition to performance, another reason to not rely on the constraint to raise an error is that tomorrow someone could change or drop it.