Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

T-SQL - Insert a row in a table only if it doesn't already exist

I have the T-SQL shown below. @Results is a table variable and 'CTE' is a common table expression. I only want to insert rows into the @Results table if the SubId I'm about to insert hasn't already been inserted into the table. The code shown below doesn't do the job and I'm not sure why. Can anyone see the problem?

Insert Into @Results (
    Cell, 
    CellSettings, 
    RecipeInstanceId, 
    BiasStartTime, 
    SubId 
    RuleInstanceId)
Select 
    Cell, 
    CellSettings, 
    RecipeInstanceId, 
    BiasStartTime, 
    SubId, 
    RuleInstanceId
From CTE
Where CTE.SubId NOT IN (Select SubId From @Results)
like image 845
Hosea146 Avatar asked Jun 08 '11 14:06

Hosea146


People also ask

How do you insert if row does not exist in SQL?

There are three ways you can perform an “insert if not exists” query in MySQL: Using the INSERT IGNORE statement. Using the ON DUPLICATE KEY UPDATE clause. Or using the REPLACE statement.

Which command insert rows that do not exist and update the rows that exist?

Using REPLACE In the event that you wish to actually replace rows where INSERT commands would produce errors due to duplicate UNIQUE or PRIMARY KEY values as outlined above, one option is to opt for the REPLACE statement.

How do you prevent duplicates from inserting into a table?

Preventing Duplicates from Occurring in a Table. You can use a PRIMARY KEY or a UNIQUE Index on a table with the appropriate fields to stop duplicate records.


3 Answers

You need to check for existance first:

IF NOT EXISTS(SELECT * FROM @Results WHERE SubId = .......)
   INSERT INTO @Results (Cell, CellSettings, RecipeInstanceId, 
                          BiasStartTime, SubId, RuleInstanceId)
     SELECT 
         Cell, CellSettings, RecipeInstanceId, 
         BiasStartTime, SubId, RuleInstanceId
     FROM CTE

Maybe you could put this requirement (only return those rows that don't already exist) into your CTE so that you won't have to filter the output from the CTE yet again...

like image 147
marc_s Avatar answered Sep 18 '22 15:09

marc_s


I would do it like this (assumption - you don't have duplicate SubID in your CTE, that is you insert SubID of X and then later in this same query you insert the same one.)

WITH CTE AS
( 
  blah
), CTENEW AS
(
   SELECT CTE.* 
   FROM CTE
   LEFT JOIN @Results R ON CTE.SubID = R.SubID
   WHERE R.SubID IS NULL
)
Insert Into @Results (
    Cell, 
    CellSettings, 
    RecipeInstanceId, 
    BiasStartTime, 
    SubId 
    RuleInstanceId)
Select 
    Cell, 
    CellSettings, 
    RecipeInstanceId, 
    BiasStartTime, 
    SubId, 
    RuleInstanceId
From CTENEW

Or you could roll the join I made into your CTE.

like image 38
Hogan Avatar answered Sep 20 '22 15:09

Hogan


Try an `except clause:

insert MyTable(c1, c2, c3)

select ot.c1, ot.c2, ot.c3
from OtherTable ot

except

select mt.c1, mt.c2, mt.c3
from MyTable
like image 22
Chris Pfohl Avatar answered Sep 19 '22 15:09

Chris Pfohl