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

Можете ли вы изменить свой ответ на использование «ВОЗВРАЩЕНИЯ», как предложил depesz? Так что нам не нужно выполнять дополнительный запрос [select customer_id от клиента, где name = 'John'] –

+0

Это не оптимизация, которую я бы сделал. Вот почему: во-первых, простое сохранение кода: если вторая вставка в порядке идентична первой, вы можете использовать тот же код для обеих вставок. Во-вторых: вряд ли будет реальная прибыль. Поскольку вы только что сделали запрос на клиента, а затем вставить, Postgres будет иметь строку и соответствующий индекс в кеше, поэтому выбор от клиента будет молниеносно. –

3

Не с регулярным заявлением, нет.

Что вы можете сделать, это обернуть функциональность в функции PL/pgsql (или на другом языке, но PL/pgsql представляется наиболее подходящей для этого), а затем просто вызовите эту функцию. Это означает, что это все равно будет одним заявлением для вашего приложения.

1

Используйте хранимые процедуры.

И даже если вы хотели бы не использовать хранимые процедуры - есть самое 3 команды, которые будут работать, а не 4. Второй получает идентификатор бесполезно, так как вы можете сделать «INSERT INTO ... ВОЗВРАЩЕНИЕ».

+0

Вы возобновляете использование процедур вместо того, чтобы выдавать не более 3 непрерывных команд SQL? Будет быстрее использовать хранимые процедуры/ –

+0

Вряд ли будет быстрее. То есть разница не должна быть измеримой. По крайней мере, предполагая разумное сетевое соединение. – 2010-01-04 12:10:49

Смежные вопросы