88

I'm writing a booking procedure for a mock airline booking database and what I really want to do is something like this:

IF EXISTS (SELECT * FROM LeadCustomer 
    WHERE FirstName = 'John' AND Surname = 'Smith') 
THEN
   INSERT INTO LeadCustomer (Firstname, Surname, BillingAddress, email) 
   VALUES ('John', 'Smith', '6 Brewery close,
            Buxton, Norfolk', '[email protected]');

But Postgres doesn't support IF statements without loading the PL/pgSQL extension. I was wondering if there was a way to do some equivalent of this or if there's just going to have to be some user interaction in this step?

2
  • Why not just load the PL/pgSQL extension, then? Commented Mar 29, 2013 at 19:30
  • @MattBall: Working with the installation of postgres on the lab computers. Using that extension isn't in the spec. Commented Mar 29, 2013 at 19:31

3 Answers 3

164

That specific command can be done like this:

insert into LeadCustomer (Firstname, Surname, BillingAddress, email)
select 
    'John', 'Smith', 
    '6 Brewery close, Buxton, Norfolk', '[email protected]'
where not exists (
    select 1 from leadcustomer where firstname = 'John' and surname = 'Smith'
);

It will insert the result of the select statement, and the select will only return a row if that customer does not exist.

Sign up to request clarification or add additional context in comments.

8 Comments

I assume there is a (very small) race here? The select subquery runs, returns 0 rows, an insert occurs in another thread, and then the LeadCustomer insert occurs?
@Kevin A primary key exception will be raised and the application will decide what to do.
I'm confused, the question doesn't mention primary keys anywhere. If there was a primary key on (firstname, surname) why wouldn't you just try the insert first?
@Kevin I would try the insert first. The question is just about syntax.
Is there a way to insert multiple rows like this?
|
8

As of 9.5 version of pgsql upsert is included, using INSERT ... ON CONFLICT DO UPDATE ...

The answer below is no longer relevant. Postgres 9.5 was released a couple years later with a better solution.

Postgres doesn't have "upsert" functionality without adding new functions.
What you'll have to do is run the select query and see if you have matching rows. If you do, then insert it.

I know you're not wanting an upsert exactly, but it's pretty much the same.

3 Comments

this will keep on increasing the auto incremented id even when there is a conflict(as insertion is attempted)
"Check the results, and conditionally insert" is prone to race conditions: If you have two threads doing it at the same time, you can get two insertions.
@CharlesDuffy not in transaction (or not if it's select for update)
-5

-- Use follwing format to insert data in any table like this --

create table user ( user_id varchar(25) primary key, phone_num numeric(15), failed_login int not null default 0, Login time timestamp );

INSERT INTO USER(user_id, phone_num, failed_login, Login time) VALUES ('12345','123456789','3',' 2021-01-16 04:24:01.755');

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.