2010-01-04 17 views
41

Ich verwende PostgreSQL.Einfügen von Daten in Tabellen, die mit Fremdschlüssel verknüpft sind

Customer 
================== 
Customer_ID | Name 

Order 
============================== 
Order_ID | Customer_ID | Price 

einen Auftrag einzufügen, hier ist das, was ich in der Regel tun müssen,

Zum Beispiel: „John“ Ort „1,34“ Preis bestellen.

(1) Get Customer_ID from Customer table, where name is "John" 
(2) If there are no Customer_ID returned (There is no John), insert "John" 
(3) Get Customer_ID from Customer table, where name is "John" 
(4) Insert "Customer_ID" and "1.34" into Order table. 

Es gibt 4 SQL-Kommunikation mit der Datenbank für diese einfache Operation beteiligt !!!

Gibt es einen besseren Weg, der mit 1 SQL-Anweisung erreicht werden kann?

Antwort

44

Sie können es in einer SQL-Anweisung für bestehende Kunden, 3 Anweisungen für neue Kunden tun. Alles, was Sie tun müssen, ist ein Optimist und zu handeln sein, als ob der Kunde bereits vorhanden ist:

insert into "order" (customer_id, price) values \ 
((select customer_id from customer where name = 'John'), 12.34); 

Wenn der Kunde nicht existiert, erhalten Sie eine SQL-Ausnahme erhalten, den Text so etwas wie sein:

null value in column "customer_id" violates not-null constraint 

(vorausgesetzt, Sie haben customer_id nicht nullfähig gemacht, was Sie sicher getan haben). Wenn die Ausnahme auftritt, legen Sie den Kunden in der Kundentabelle und wiederholen Sie den Einsatz in die Auftragstabelle:

insert into customer(name) values ('John'); 
insert into "order" (customer_id, price) values \ 
((select customer_id from customer where name = 'John'), 12.34); 

Es sei denn, Ihr Unternehmen mit einer Rate wächst, die machen „wo alle setzen Geld“ Ihre einzige wirkliche Problem, die meisten Ihrer Einsätze werden für bestehende Kunden sein. In den meisten Fällen wird die Ausnahme nicht auftreten und Sie werden in einer Anweisung ausgeführt.

+0

Können Sie Ihre Antwort ändern, um "RETURNING" als Depesz vorgeschlagen zu verwenden? Damit wir keine zusätzliche Abfrage durchführen müssen [select customer_id vom Kunden where name = 'John'] –

+0

Das ist keine Optimierung, die ich machen würde. Hier ist der Grund: Erstens, den Code einfach zu halten: Wenn der zweite Insert in der Reihenfolge identisch mit dem ersten ist, können Sie den gleichen Code verwenden, um beide Inserts zu tun. Zweitens: Es wird wahrscheinlich keinen wirklichen Leistungszuwachs geben. Da Sie gerade die Abfrage für den Kunden und dann die Einfügung durchgeführt haben, wird Postgres die Zeile und den entsprechenden Index im Cache haben, so dass die Auswahl des Kunden blitzschnell erfolgt. –

3

Nicht mit einer regulären Aussage, nein.

Sie können die Funktionalität in eine PL/pgsql-Funktion (oder eine andere Sprache, aber PL/pgsql scheint dafür am besten geeignet), und rufen Sie dann diese Funktion. Das bedeutet, dass es immer noch eine einzige Aussage zu Ihrer App sein wird.

1

Gespeicherte Prozeduren verwenden.

Und selbst wenn Sie würde nicht wollen, gespeicherte Prozeduren verwenden - ist es höchstens 3 Befehle ausführen, nicht 4. Zweite bekommen id nutzlos sein, wie Sie „INSERT INTO ... RÜCKKEHR“ tun können.

+0

Beginnen Sie wieder, Prozeduren zu verwenden, anstatt maximal 3 fortlaufende SQL-Befehle auszugeben? Werden gespeicherte Prozeduren schneller sein/ –

+0

Unwahrscheinlich, schneller zu sein. I.e. Der Unterschied sollte nicht messbar sein. Zumindest unter der Annahme einer vernünftigen Netzwerkverbindung. –

Verwandte Themen