Russian Qt Forum

Программирование => Базы данных => Тема начата: Viktor от Июль 14, 2016, 14:27



Название: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: Viktor от Июль 14, 2016, 14:27
Пытаюсь сделать так, что бы запрос INSERT не добавлял строки с одинаковыми данными. Наткнулся на такую команду как INSERT ....... ON CONFLICT.

Моя задача сделать так: если все столбцы одинаковые, кроме идентификационного номера, то запись просто не добавляется. Сделал следующим образом:

INSERT INTO "Apartments"
("name", "kvm", "rooms", "etaj", "date_add", "date_update")
VALUES
('Новый дом', 26, 3, 4, '2016-06-29 12:12:43', '2016-07-11 10:50:37')
ON CONFLICT ("name", "kvm", "rooms", "etaj", "date_add", "date_update") DO NOTHING;

не не вышло, может кто подскажет в чём тут проблема?


Название: Re: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: PimenS от Июль 14, 2016, 14:41
Насколько я понял из документации conflict_target должны быть определены как UNIQUE.

По крайней мере у меня так работает.

Код:
CREATE TABLE n_catalogs.slist_search_text
(
  search_text character varying NOT NULL, -- Строка поиска
  search_quantity bigint NOT NULL, -- Количество
  search_type integer NOT NULL, -- Тип поиска
  CONSTRAINT slist_search_text_text_type_pkey PRIMARY KEY (search_text, search_type)
);

Код:
q.prepare("INSERT INTO n_catalogs.slist_search_text AS old (search_text, search_quantity, search_type) "
              "VALUES (?, 1, ?) ON CONFLICT (search_text, search_type) "
              "DO UPDATE SET search_quantity = old.search_quantity + 1;");


Название: Re: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: Viktor от Июль 14, 2016, 15:32
Насколько я понял из документации conflict_target должны быть определены как UNIQUE.

По крайней мере у меня так работает.

Код:
q.prepare("INSERT INTO n_catalogs.slist_search_text AS old (search_text, search_quantity, search_type) "
              "VALUES (?, 1, ?) ON CONFLICT (search_text, search_type) "
              "DO UPDATE SET search_quantity = old.search_quantity + 1;");

Я верно понял, что ON CONFLICT (search_text, search_type) сравнивает поля search_text, search_type и если они одинаковые, то добавление записи игнорируется?


Название: Re: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: PimenS от Июль 14, 2016, 15:56
В моем случае просто выполняется UPDATE, если сделать DO NOTHING, то запись игнорируется.

Ну т.е если есть например таблица

Код:
CREATE TABLE test
(
  stext character varying NOT NULL,
  squantity bigint NOT NULL,
  CONSTRAINT text_pkey PRIMARY KEY (stext, squantity)
);

Добавим туда данные

Код:
INSERT INTO test VALUES('A', 1), ('B', 1);

Если использовать ON CONFLICT

Код:
INSERT INTO test(stext, squantity) VALUES('A', 1) ON CONFLICT (stext, squantity) DO NOTHING;

То такая запись не добавится. А вот если

Код:
INSERT INTO test(stext, squantity) VALUES('A', 2) ON CONFLICT (stext, squantity) DO NOTHING;

то запишется.

ЗЫ. Не сравниваются search_text с search_type. Ищутся записи search_text, search_type и если в базе уже есть такая пара, то тогда и срабатывает исключение.


Название: Re: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: Viktor от Июль 14, 2016, 17:12
Большое спасибо! Всё получилось! Дело было ещё в том, что нужно было указать в настройках таблицы, какие столбцы являются уникальными!


Название: Re: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: PimenS от Июль 14, 2016, 17:41
Так об этом я и говорил

Цитировать
conflict_target должны быть определены как UNIQUE.


Название: Re: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: Viktor от Июль 14, 2016, 17:46
Так об этом я и говорил

Цитировать
conflict_target должны быть определены как UNIQUE.

да, просто я не сразу понял, я с этим впервые сталкиваюсь)


Название: Re: PostgreSQL автоматическое игнорирование добавления одинаковых строк
Отправлено: PimenS от Июль 14, 2016, 17:59
Ну это у всех так. ON CONFLICT только в 9.5 появилось. Мало кто сразу на новый релиз переходит. А плюшка очень полезная.