Многорядная условная вставка со значениями DEFAULT - PullRequest
0 голосов
/ 17 января 2019

Вот упрощенная версия запроса PostgreSQL для вставки нескольких строк в таблицу:

INSERT INTO my_table (a, b, datasource)
VALUES
  ('foo', 'bar', 'my source'),
  ('foo', DEFAULT, 'my source'),
  (DEFAULT, 'bar', 'my source');

Обратите внимание, что значение DEFAULT может отображаться в столбце a или b.

Это работает нормально, однако я хочу вставить только строки, которые соответствуют некоторым критериям, и дополнительно было бы неплохо удалить дублирование для значений, которые являются постоянными для всех вставляемых строк.

Поэтому я пытаюсь изменить его на что-то вроде этого:

INSERT INTO my_table (a, b, datasource)
SELECT v.*, 'my source'
FROM (VALUES ('foo', 'bar'), ('foo', DEFAULT), (DEFAULT, 'bar')) AS v (a, b)
WHERE v.a = 'foo';

Это приводит к ошибке: DEFAULT is not allowed in this context.

Как мне обойти это?

Возможно, стоит отметить, что в действительности условие WHERE на самом деле является сложным и включает в себя другие таблицы. Также есть несколько тысяч строк для вставки за раз, причем выражения значений генерируются программно. Можно сделать так, чтобы буквальные значения по умолчанию для таблицы выводились вместо DEFAULT, однако это требует жесткого кодирования их вне базы данных, чего я хочу избежать (потому что, если я изменю их в БД и забуду обновить жестко закодированные значения, это вызовет проблемы).

1 Ответ

0 голосов
/ 19 мая 2019

Так как я не смог найти ничего более изящного (о чем свидетельствует отсутствие других ответов), я в итоге воспользовался предложением сначала вставить значения во временную таблицу. PostgreSQL позволяет действительно легко создать таблицу «клонирования» ( с использованием ключевого слова LIKE ) с теми же значениями по умолчанию, но без некоторых других ненужных вещей:

CREATE TEMPORARY TABLE temp_table (
  LIKE my_table INCLUDING DEFAULTS
);

INSERT INTO temp_table (a, b)
VALUES
  ('foo', 'bar'),
  ('foo', DEFAULT),
  (DEFAULT, 'bar');

Тогда это просто вопрос использования временной таблицы вместо предложения VALUES:

INSERT INTO my_table (a, b, datasource)
SELECT a, b, 'my source'
FROM temp_table
WHERE a = 'foo';

Одно небольшое предостережение в том, что вы не можете избежать копирования ограничений NOT NULL во временную таблицу. Например, если столбец datasource был NOT NULL (и не имел значения по умолчанию), мне пришлось бы добавить значение (или заполнитель) в первом запросе INSERT или удалить столбец.

...