ВЫБЕРИТЕ или ВСТАВЬТЕ строку в одной команде
Я использую PostgreSQL 9.0, и у меня есть таблица с только искусственным ключом (автоинкрементная последовательность) и еще один уникальный ключ. (Да, есть причина для этой таблицы.:)) Я хочу искать идентификатор другим ключом или, если он не существует, вставьте его:
SELECT id
FROM mytable
WHERE other_key = 'SOMETHING'
Затем, если нет совпадения:
INSERT INTO mytable (other_key)
VALUES ('SOMETHING')
RETURNING id
Вопрос: можно ли сохранить двустороннюю поездку в БД, выполнив оба из них в одном утверждении? Я могу вставить строку, если она не существует следующим образом:
INSERT INTO mytable (other_key)
SELECT 'SOMETHING'
WHERE NOT EXISTS (SELECT * FROM mytable WHERE other_key = 'SOMETHING')
RETURNING id
... но это не дает идентификатор существующей строки. Есть идеи? Существует уникальное ограничение на other_key, если это помогает.
Ответы
Ответ 1
Вы пытались объединить его?
Изменить - для этого требуется Postgres 9.1:
create table mytable (id serial primary key, other_key varchar not null unique);
WITH new_row AS (
INSERT INTO mytable (other_key)
SELECT 'SOMETHING'
WHERE NOT EXISTS (SELECT * FROM mytable WHERE other_key = 'SOMETHING')
RETURNING *
)
SELECT * FROM new_row
UNION
SELECT * FROM mytable WHERE other_key = 'SOMETHING';
приводит к:
id | other_key
----+-----------
1 | SOMETHING
(1 row)
Ответ 2
вы можете использовать хранимую процедуру
IF (SELECT id FROM mytable WHERE other_key = 'SOMETHING' LIMIT 1) < 0 THEN
INSERT INTO mytable (other_key) VALUES ('SOMETHING')
END IF
Ответ 3
Нет, нет специального синтаксиса SQL, который позволяет вам выбирать или вставлять. Вы можете делать то, что Илия упоминает и создает sproc, а это значит, что он не будет совершать круговую поездку от клиента к серверу, но он все равно приведет к двум запросам (три фактически, если вы считаете сам sproc).