I want to do some quick inserts but avoid duplicates into a Table.
For argument’s sake lets call it MarketPrices, I’ve been experimenting with two ways of doing it but not sure how to benchmark which will be faster.
INSERT INTO MarketPrices (SecurityCode, BuyPrice, SellPrice, IsMarketOpen)
SELECT @SecurityCode, @BuyPrice, @SellPrice, @IsMarketOpen
EXCEPT
SELECT SecurityCode, BuyPrice, SellPrice, j.bool as IsActive FROM MarketPrices
CROSS JOIN (SELECT 0 as bool UNION SELECT 1 as bool ) as j
OR
DECLARE @MktId int
SET @MktId = (SELECT SecurityId FROM MarketPrices
where SecurityCode = @SecurityCode
and BuyPrice=@BuyPrice
and SellPrice = @SellPrice)
IF (@MktId is NULL)
BEGIN
INSERT INTO MarketPrices (SecurityCode, BuyPrice, SellPrice, IsMarketOpen)
VALUES
(@SecurityCode,@BuyPrice, @SellPrice, @IsMarketOpen)
END
Assume that @whatever is an input parameter in the stored procedure.
I want to be able to insert a new record for every SecurityCode when the BuyPrice or SellPrice or both are different from every other previous occurance. I don’t care about IsMarketOpen.
Is there anything glaringly stupid about either of the above approaches? Is one faster than the other?
EDIT: to prevent race conditions in concurrent environments, use
WITH (UPDLOCK)in the correlated subquery orEXCEPT‘dSELECT. The test script I wrote below doesn’t require it, since it uses temporary tables that are only visible to the current connection, but in a real environment, operating against user tables, it would be necessary.MERGEdoesn’t requireUPDLOCK.Inspired by mcl’s answer re: unique index & let the database throw an error, I decided to benchmark conditional inserts vs. try/catch.
The results appear to support the conditional insert over try/catch, but YMMV. It’s a very simple scenario (one column, small table, etc), executed on one machine, etc.
Here are the results (SQL Server 2008, build 10.0.1600.2):
Notice, even on unique inserts, there’s slightly more overhead to try/catch than a conditional insert. I wonder if this varies by version, CPU, number of cores, etc.
I did not benchmark the
IFconditional inserts, justWHERE. I assume theIFvariety would show more overhead, since a) would you have two statements, and b) you would need to wrap the two statements in a transaction and set the isolation level to serializable (!). If someone wanted to test this, you would need to change the temp table to a regular user table (serializable doesn’t apply to local temp tables).Here is the script: