2010-01-04 35 views
41

Tôi đang sử dụng PostgreSQL.Chèn dữ liệu vào các bảng được liên kết bằng khóa ngoài

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

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

Để chèn một trật tự, đây là những gì tôi cần phải làm thường,

Ví dụ, "John" nơi "1,34" giá theo thứ tự.

(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. 

Có 4 giao tiếp SQL với cơ sở dữ liệu liên quan đến hoạt động đơn giản này !!!

Có cách nào tốt hơn, có thể đạt được bằng cách sử dụng 1 câu lệnh SQL không?

Trả lời

44

Bạn có thể làm điều đó trong một câu lệnh sql cho khách hàng hiện tại, 3 báo cáo cho những khách hàng mới. Tất cả bạn phải làm là trở thành một người lạc quan và hành động như thể khách hàng đã tồn tại:

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

Nếu khách hàng không tồn tại, bạn sẽ nhận được một ngoại lệ sql mà văn bản sẽ là một cái gì đó như:

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

(cung cấp cho bạn customer_id không thể vô hiệu hóa, mà tôi chắc chắn bạn đã làm). Khi ngoại lệ xảy ra, chèn khách hàng vào bảng khách hàng và làm lại chèn vào bảng theo thứ tự:

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

Trừ khi doanh nghiệp của bạn đang phát triển với một tốc độ mà sẽ làm cho "nơi để đặt tất cả số tiền" của bạn chỉ thực vấn đề, hầu hết các phụ trang của bạn sẽ dành cho khách hàng hiện tại. Vì vậy, hầu hết thời gian, ngoại lệ sẽ không xảy ra và bạn sẽ được thực hiện trong một tuyên bố.

+0

Bạn có thể sửa đổi câu trả lời của mình để sử dụng "RETURNING" như depesz được đề xuất không? Vì vậy, chúng tôi không cần thực hiện truy vấn bổ sung [chọn customer_id từ khách hàng nơi name = 'John'] –

+0

Đó không phải là một tối ưu hóa tôi sẽ làm. Đây là lý do: Thứ nhất, giữ mã đơn giản: Nếu lần chèn thứ hai vào thứ tự giống với mã đầu tiên, bạn có thể sử dụng cùng một mã để thực hiện cả hai lần chèn. Thứ hai: Không có khả năng đạt được hiệu suất thực sự. Vì bạn vừa mới thực hiện truy vấn trên khách hàng, và sau đó chèn, Postgres sẽ có hàng và chỉ mục thích hợp trong bộ nhớ cache, do đó, lựa chọn từ khách hàng sẽ nhanh như chớp. –

3

Không có tuyên bố thông thường, không.

Những gì bạn có thể làm là bọc chức năng trong hàm PL/pgsql (hoặc ngôn ngữ khác, nhưng PL/pgsql có vẻ thích hợp nhất), và sau đó chỉ cần gọi hàm đó. Điều đó có nghĩa là nó vẫn sẽ là một tuyên bố duy nhất cho ứng dụng của bạn.

1

Sử dụng quy trình được lưu trữ.

Và thậm chí giả sử bạn không muốn sử dụng thủ tục được lưu trữ - có tối đa 3 lệnh để chạy, không phải 4. ID nhận thứ hai là vô ích, vì bạn có thể thực hiện "INSERT INTO ... RETURNING".

+0

Bạn có bắt đầu sử dụng các thủ tục không, thay vì phát hành tối đa 3 lệnh SQL liên tục? Việc sử dụng các thủ tục được lưu trữ sẽ nhanh hơn/ –

+0

Không thể nhanh hơn. I E. sự khác biệt không thể đo lường được. Ít nhất là giả sử kết nối mạng hợp lý. –

Các vấn đề liên quan