I've been searching around for a question similar to this for awhile now, and I haven't found anything, so if this has been asked before, this will at least serve as a good pointer for those ignorant of the proper nomenclature.
I want to INSERT INTO
a table if a row doesn't already exist, based on a unique key. It it does exist, then I want to get the primary key Id of that row.
Imagine a table that holds email addresses:
EmailAddressId(PK) | EmailAddress(UK)
I want to INSERT
into that table a new Email Address, but there is a unique constraint on EmailAddress
. Thus, if the new Email Address is the same as an existing, the INSERT
will fail. In that case, I want to select the existing EmailAddressId
from the database for the EmailAddress
.
I want to do this in the fewest number of operations, assuming that collisions will be a rare case.
Thus, I setup a TRY...CATCH
block within a Stored Procedure as follows:
ALTER PROCEDURE [dbo].[EmailAddressWrite]
@EmailAddress nvarchar[256]
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
DECLARE @EmailAddressId INT
BEGIN TRY
INSERT INTO EmailAddress VALUES (@EmailAddress)
SET @EmailAddressId = (SELECT SCOPE_IDENTITY())
END TRY
BEGIN CATCH
SET @EmailAddressId = (SELECT EmailAddressId FROM EmailAddress WHERE EmailAddress = @EmailAddress)
END CATCH
--Do some more stuff with the Id now.
COMMIT TRANSACTION
RETURN @EmailAddressId
END
The code above functions, and produces the required result, but the Internet makes me think that using TRY...CATCH
in this fashion might be slow...thus I'm unsure if this is an optimal solution.
I've only found one other solution which is to SELECT
first, and INSERT
second. This would result in 2 operations almost all of the time, as I am anticipating very few duplicate email addresses (at least for a month or more).
- Is this the optimal solution to achieve 1 operation on
INSERT
and 2 operations onINSERT
fail? - What other solutions can achieve 1 operation on
INSERT
and 2 operations onINSERT
fail?
If I've misused any terminology, please correct it.