[Note: I found a few answers for this, such as 9911659 and 16636698, but they were not quite clear enough on the syntax.]
I want to insert a row into a table, but only if that row does not already exist. The column values for the inserted row come from variables (procedure arguments) and not from another table, so I won't be using merge
.
I do not want to use a separate if exists
followed by an insert
, but rather I'd like to accomplish this in a single (insert
) statement.
I have @bookID
, @userID
, @reviewDate
, and @reviewYear
as arguments to my proc, which I want to insert into the new row into table my_table
.
So I have this:
insert into my_table
(bookID, reviewYear, userID, reviewDate)
select
@bookID, @reviewYear, @userID, @reviewDate -- Proc arguments, values for new row
from my_table
where not exists (
select bookID -- Find existing matching row
from my_table
where bookID = @bookID
and reviewYear = @reviewYear
)
In other words, the insert
adds a new row only if there is not already an existing row with the same bookID
and reviewYear
. So a given user can add a review for a given book for a given year, but only if no user has already done so.
Have I got this correct, or is there a simpler syntax to accomplish the same thing (in a single statement)?
Addendum (2020-Jan-10)
As pointed out, the select
will choose multiple rows, and the whole insert
statement will end up inserting many rows, potentially as many rows as there are currently in my_table
.
A second attempt, which adds a distinct
clause to the select
:
insert into my_table
(bookID, reviewYear, userID, reviewDate)
select distinct -- Only one possible match
@bookID, @reviewYear, @userID, @reviewDate -- Proc arguments, values for new row
from my_table
where not exists (
select bookID -- Find existing matching row
from my_table
where bookID = @bookID
and reviewYear = @reviewYear
)