SQL Server Insert if not exists SQL Server Insert if not exists sql-server sql-server

SQL Server Insert if not exists


instead of below Code

BEGIN   INSERT INTO EmailsRecebidos (De, Assunto, Data)   VALUES (@_DE, @_ASSUNTO, @_DATA)   WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos                    WHERE De = @_DE                   AND Assunto = @_ASSUNTO                   AND Data = @_DATA);END

replace with

BEGIN   IF NOT EXISTS (SELECT * FROM EmailsRecebidos                    WHERE De = @_DE                   AND Assunto = @_ASSUNTO                   AND Data = @_DATA)   BEGIN       INSERT INTO EmailsRecebidos (De, Assunto, Data)       VALUES (@_DE, @_ASSUNTO, @_DATA)   ENDEND

Updated : (thanks to @Marc Durdin for pointing)

Note that under high load, this will still sometimes fail, because a second connection can pass the IF NOT EXISTS test before the first connection executes the INSERT, i.e. a race condition. See stackoverflow.com/a/3791506/1836776 for a good answer on why even wrapping in a transaction doesn't solve this.


For those looking for the fastest way, I recently came across these benchmarks where apparently using "INSERT SELECT... EXCEPT SELECT..." turned out to be the fastest for 50 million records or more.

Here's some sample code from the article (the 3rd block of code was the fastest):

INSERT INTO #table1 (Id, guidd, TimeAdded, ExtraData)SELECT Id, guidd, TimeAdded, ExtraDataFROM #table2WHERE NOT EXISTS (Select Id, guidd From #table1 WHERE #table1.id = #table2.id)-----------------------------------MERGE #table1 as [Target]USING  (select Id, guidd, TimeAdded, ExtraData from #table2) as [Source](id, guidd, TimeAdded, ExtraData)    on [Target].id =[Source].idWHEN NOT MATCHED THEN    INSERT (id, guidd, TimeAdded, ExtraData)    VALUES ([Source].id, [Source].guidd, [Source].TimeAdded, [Source].ExtraData);------------------------------INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData)SELECT id, guidd, TimeAdded, ExtraData from #table2EXCEPTSELECT id, guidd, TimeAdded, ExtraData from #table1------------------------------INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData)SELECT #table2.id, #table2.guidd, #table2.TimeAdded, #table2.ExtraDataFROM #table2LEFT JOIN #table1 on #table1.id = #table2.idWHERE #table1.id is null


I would use a merge:

create PROCEDURE [dbo].[EmailsRecebidosInsert]  (@_DE nvarchar(50),   @_ASSUNTO nvarchar(50),   @_DATA nvarchar(30) )ASBEGIN   with data as (select @_DE as de, @_ASSUNTO as assunto, @_DATA as data)   merge EmailsRecebidos t   using data s      on s.de = t.de     and s.assunte = t.assunto     and s.data = t.data    when not matched by target    then insert (de, assunto, data) values (s.de, s.assunto, s.data);END