Можно ли вернуть идентификаторы многострочной вставки в SQL?

С приведенным ниже оператором я могу вставить несколько строк в таблицу. Если тег уже существует, ничего не происходит, а если он не существует, он создает строку.

INSERT INTO tags (name) VALUES ('this'),('is'),('my'),('interest'),('list'),('running'),('pokemongo'),('fighting'),('eating') ON CONFLICT DO NOTHING;

Можно ли вернуть идентификатор всех этих значений независимо от того, существуют они или нет?

Я использую python psycopg2 с postgres 9.5.


person DigitalDisaster    schedule 25.08.2016    source источник


Ответы (2)


Это можно сделать в одном запросе, используя блок WITH (см. документацию PostgreSQL на странице WITH). и SELECT). Например:

WITH t1 (c1) AS ( VALUES ('this'),('is'),... ),
t2 AS (SELECT id FROM tags WHERE name IN (SELECT c1 FROM t1) ),
t3 AS (INSERT INTO tags (name) SELECT c1 FROM t1 ON CONFLICT DO NOTHING RETURNING id)
SELECT id from t2
UNION
SELECT id from t3;

Вы также можете заменить ON CONFLICT DO NOTHING на WHERE c1 NOT IN (SELECT name FROM tags). Это будет работать, не полагаясь на конфликт, вызванный уникальным индексом.

person ASL    schedule 25.08.2016
comment
Хм, я получаю синтаксическую ошибку в строке INSERT или рядом с ней. Будет читать больше в WITH - person DigitalDisaster; 25.08.2016
comment
Извините, это моя ошибка. Я забыл, что UNION может присоединяться только к операторам SELECT. Смотрите отредактированный ответ. Запрос, вероятно, можно было бы упростить, немного подумав. - person ASL; 25.08.2016
comment
Это фантастический ответ. Помогли мне понять немного больше о некоторых других вещах. Большое спасибо за ваше время. - person DigitalDisaster; 25.08.2016

INSERT INTO 
    tags (name) 
VALUES 
    ('this'),('is'),('my'),('interest'),('list'),('running'),('pokemongo'),('fighting'),('eating') 
ON CONFLICT DO NOTHING 
RETURNING ID; # <== this is what you need.

Изменить. Верно, с этим решением вы получите идентификаторы только вставленных строк.

Если вам нужны все идентификаторы, вам придется сделать еще один запрос:

select ID from tags where name in ('this', 'is', 'my', 'interestest', 'list', '...')
person Loïc    schedule 25.08.2016
comment
Пробовал это. Это возвращает идентификатор только в том случае, если строка вставлена, но если эта строка уже существует, она ничего не вернет. - person DigitalDisaster; 25.08.2016
comment
Да, я надеялся, что смогу избежать этого второго запроса. Но спасибо, что выстрелил. - person DigitalDisaster; 25.08.2016