2013-03-29 7 views
21

Ich bin eine Buchung für ein Mock Fluggesellschaft Buchung Datenbank zu schreiben und was ich will, ist wirklich etwas zu tun, wie folgt aus:Bedingte INSERT INTO-Anweisung in Postgres

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]'); 

Aber Postgres unterstützt nicht IF Aussagen ohne Laden der PL/pgSQL-Erweiterung. Ich habe mich gefragt, ob es eine Möglichkeit gibt, etwas Ähnliches zu tun, oder ob es in diesem Schritt nur eine Benutzerinteraktion geben muss?

+0

Warum nicht einfach nur die PL/pgSQL-Erweiterung laden? –

+0

@MattBall: Arbeiten mit der Installation von Postgres auf den Laborcomputern. Die Verwendung dieser Erweiterung ist nicht in der Spezifikation. –

Antwort

45

Der spezifische Befehl wie dies getan werden kann:

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

Es wird das Ergebnis der select-Anweisung einfügen, und die select wird nur eine Zeile zurück, wenn dieser Kunde nicht existiert.

+1

Ich nehme an, dass es hier eine (sehr kleine) Rasse gibt? Die Select-Unterabfrage wird ausgeführt, gibt 0 Zeilen zurück, eine Einfügung findet in einem anderen Thread statt, und dann tritt die LeadCustomer-Einfügung auf? –

+0

@Kevin Eine Ausnahme für den Primärschlüssel wird ausgelöst, und die Anwendung entscheidet, was zu tun ist. –

+1

Ich bin verwirrt, die Frage erwähnt Primärschlüssel nirgendwo. Wenn es einen Primärschlüssel gab (Vorname, Nachname), warum sollten Sie nicht zuerst den Einsatz ausprobieren? –

1

Ab 9.5 Version von pgsql Upsert ist, enthalten INSERT ... ON CONFLICT DO UPDATE ...

Die Antwort unter Verwendung von nicht mehr relevant ist. Postgres 9.5 wurde einige Jahre später mit einer besseren Lösung veröffentlicht.

Postgres hat keine "upsert" Funktionalität, ohne neue Funktionen hinzuzufügen.
Was Sie tun müssen, ist die Select-Abfrage ausführen und sehen, ob Sie übereinstimmende Zeilen haben. Wenn Sie dies tun, fügen Sie es ein.

Ich weiß, dass Sie nicht genau ein upsert wollen, aber es ist ziemlich das Gleiche.

+0

Es gibt eine Möglichkeit, dies zu tun: http://StackOverflow.com/a/8702291/330315 –

+0

Dies wird die automatisch inkrementierte ID auch dann weiter erhöhen, wenn ein Konflikt vorliegt (da die Einfügung versucht wird) – rohanagarwal

+0

"Überprüfen Sie die Ergebnisse, und bedingt einfügen "ist anfällig für Race Conditions: Wenn Sie zwei Threads haben, die es gleichzeitig tun, können Sie zwei Insertionen bekommen. –