Импорт CSV в Postgres: обновление и вставка одновременно

Итак, я новичок в Postgresql и начал работать с ним, протестировав некоторые вещи с помощью pgadmin4 на Postgres 9.6.

Проблема:

У меня есть таблица: тест (id, текст)

В этой таблице у меня есть 10 строк данных. Теперь я хочу импортировать CSV с 12 строками для обновления тестовой таблицы. Некоторый текст изменился для первых 10 строк, И я хочу вставить 2 дополнительные строки из CSV.

Я знаю, что вы можете обрезать все данные из таблицы и просто снова импортировать все из CSV, но это не лучший способ сделать это. Я хочу обновить существующие данные и вставить новые данные одним запросом.

Я уже нашел функцию, которая должна решить эту проблему с помощью временной таблицы. Это правильно обновляет существующие строки, но 2 дополнительные строки не вставляются.

CREATE OR REPLACE FUNCTION upsert_test(integer,varchar) RETURNS VOID AS $$
DECLARE
BEGIN
    UPDATE test
SET id = tmp_table.id,
text = tmp_table.text
FROM tmp_table
WHERE test.id = tmp_table.id;
IF NOT FOUND THEN
INSERT INTO test(id,text) values 
(tmp_table.id,tmp_table.text);
END IF;
END;
$$ Language 'plpgsql';

DO $$ BEGIN
PERFORM upsert_test(id,text) FROM test;
END $$;

Итак, что мне нужно изменить, чтобы вставка тоже работала?


person StackAsk    schedule 31.05.2017    source источник
comment
Не связано, но: название языка является идентификатором. Не заключайте его в одинарные кавычки, используйте: language plpgsql   -  person a_horse_with_no_name    schedule 31.05.2017


Ответы (1)


Предполагая, что у вас есть первичное или уникальное ограничение для столбца id, вы можете сделать это с помощью одного оператора, никаких функций не требуется:

insert into test (id, text)
select id, text
from tmp_table
on conflict (id) 
  do update set text = excluded.text;
person a_horse_with_no_name    schedule 31.05.2017
comment
Да, я пробовал это первым, но всегда получал ошибку: подзапрос возвращает более одной строки. - person StackAsk; 31.05.2017
comment
@StackAsk: тогда вы использовали другой запрос. Запрос в ответе не приведет к этой ошибке - person a_horse_with_no_name; 31.05.2017
comment
О да, мой плохой. Работал нормально. Благодарю вас! - person StackAsk; 31.05.2017