2010-01-04 205 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

相关问题