2010-01-04 203 views
41

我正在使用PostgreSQL。將數據插入到通過外鍵鏈接的表中

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

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

要插入的順序,這裏是我需要平時做,

例如,「約翰」的地方「1.34」價格秩序。

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

有4個SQL通信數據庫涉及這個簡單的操作!

有沒有更好的方法,使用1個SQL語句可以實現?

回答

44

你可以在一個sql語句中爲現有客戶做到這一點,3個語句爲新的。所有您需要做的是一個樂觀主義者,並充當雖然客戶已經存在:

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

如果客戶不存在,你會得到一個SQL例外,其文本將是這樣的:

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

(提供您使customer_id不可爲空,我相信您確實是這樣做的)。當異常發生時,插入客戶到客戶表,並重新插入到順序表:

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

除非你的企業以一定的速率,這將使越來越多「裏把所有的錢」你唯一的真正的問題,您的大部分插入將爲現有客戶。所以,大多數情況下,這種例外情況不會發生,您將在一個聲明中完成。

+0

你可以修改你的答案,使用「RETURNING」作爲depesz建議?所以我們不需要執行額外的查詢[從customer選擇customer_id where name ='John'] – 2010-01-05 08:04:29

+0

這不是我要做的優化。原因如下:首先,保持代碼簡單:如果第二次插入順序與第一次插入相同,則可以使用相同的代碼執行兩次插入。其次:不可能有真正的性能提升。由於您剛剛完成了對客戶的查詢,然後插入,因此Postgres將在緩存中包含該行和相應的索引,因此從客戶中選擇的內容將閃電般快速。 – 2010-01-05 14:51:21

3

沒有正式聲明,沒有。

你可以做的是將函數包裝在PL/pgsql函數(或其他語言,但PL/pgsql似乎是最合適的),然後調用該函數。這意味着它仍然是您的應用程序的單一聲明。

1

使用存儲過程。

甚至假設您不想使用存儲過程 - 最多有要運行的命令,而不是4.第二次獲取id無用,正如您可以執行「INSERT INTO ... RETURNING」一樣。

+0

你是否重新開始使用過程,而不是發出至多3個連續的SQL命令?將使用存儲過程更快/ – 2010-01-04 10:22:41

+0

不可能更快。即差異不應該是可衡量的。至少假設明智的網絡連接。 – 2010-01-04 12:10:49

相關問題