Мы часто используем быстрые одноразовые файлы SQL для вставки или обновления данных в существующей базе данных.SQL обычно пишется разработчиком, тестируется в системе разработки и затем импортируется в рабочую БД с psql -U dbuser dbname < file.sql
.
. (Тривиальный) пример может выглядеть следующим образом:
INSERT INTO employees (
company_id,
name,
position,
created_by,
last_modified_by
) VALUES
(
(SELECT id FROM companies WHERE name = 'Acme Fellowship'),
'Frodo Baggins',
'Ring bearer',
(SELECT id FROM users WHERE login = 'admin'),
(SELECT id FROM users WHERE login = 'admin')
),
(
(SELECT id FROM companies WHERE name = 'Acme Fellowship'),
'Samwise Gamgee',
'Rope bearer',
(SELECT id FROM users WHERE login = 'admin'),
(SELECT id FROM users WHERE login = 'admin')
),
(
(SELECT id FROM companies WHERE name = 'Acme Fellowship'),
'Peregrin Took',
'Ent rider',
(SELECT id FROM users WHERE login = 'admin'),
(SELECT id FROM users WHERE login = 'admin')
);
Хотя это работает, в подзапросах много повторяющегося кода.Было бы неплохо (более эффективно и менее подвержено ошибкам) хранить соответствующие значения для companies.id
и users.id
во временных переменных.В этом интерпретируемом примере разница в производительности, вероятно, минимальна, но на практике у нас действительно есть более сложные запросы и обновления, и часто имеется более трех обновленных / вставленных записей.
Тот же пример, написанный для MySQL, выглядит следующим образомthis:
SELECT @company_id := id FROM companies WHERE name = 'Acme Fellowship';
SELECT @admin_id := id FROM users WHERE login = 'admin';
INSERT INTO employees (
company_id,
name,
position,
created_by,
last_modified_by
) VALUES
(@company_id, 'Frodo Baggins', 'Ring bearer', @admin_id, @admin_id),
(@company_id, 'Samwise Gamgee', 'Rope bearer', @admin_id, @admin_id),
(@company_id, 'Peregrin Took', 'Ent rider', @admin_id, @admin_id);
Есть ли способ достичь чего-то похожего в PostgreSQL?
На что я смотрел:
- переменные сессии psql (с помощью
\set
): нельзя использовать для хранения результатов запроса - plpgsql: можно использовать только в процедуре (мы все еще выполняем 8.4)
- временных таблиц: я не вижу, как это сделатьиспользуйте их, не создавая уродливых и запутанных утверждений
Если нет прямого эквивалента для Postgres, что, по вашему мнению, было бы наименее неуклюжим способом создания файлов обновлений такого типа?