Skip to content

sql_do_upsert

do- edited this page Jan 22, 2018 · 1 revision

Описание

Внесение одной или нескольких записей в заданную таблицу в режиме синхронизации данных: то есть, возможно, поверх существующего содержимого.

Ключ синхронизации на каждую таблицу может быть только один. Он описывается в модели данных в виде условно-уникального индекса.

Процедура реализуется через атомарные UPSERT-операторы SQL (INSERT ... ON CONFLICT, MERGE INTO) без дополнительных блокировок.

Пример

Рассмотрим таблицу geo, описанную в модели данных следующим образом:

label => 'Географические координаты',

columns => {
	label               => 'string',              # Адрес
	lat                 => 'decimal[8,6]',        # Широта
	lon                 => 'decimal[8,6]',        # Долгота
},

keys => {
	label => 'label!',
},

Поскольку определение ключа оканчивается на '!', индекс будет уникальным по множеству с fake=0 (в то же время дублей по label с иными значениями fake может быть сколько угодно).

Теперь 2 вызова подряд

 my $id_1 = sql_do_upsert (geo => {label => 'Офис', lat => 0, lon => 0, fake => 0});
 my $id_2 = sql_do_upsert (geo => {label => 'Офис', lat => 55, lon => 37.392113, fake => 0});

приведут к тому, что в таблице geo будет ровно одна запись с label='Офис' и координатами 55 37.392113, а в переменных $id_1 и $id_2 — одно и то же значение: id этой записи.

Последующий вызов

 sql_do_upsert (geo => {label => 'Офис', lat => 55.805393, lon => undef, fake => 0});

уточнит значение поля lat, но не затронет lon: пустые значения игнорируются, даже если переданы явно, но непустые будут записаны в любом случае (в отличие от sql_select_id, где это регулируется префиксом -).

За один вызов можно передать и целый пакет записей:

 sql_do_upsert (geo => [
   {label => 'Офис',    lat => 55.805393, lon => 37.392113, fake => 0},
   # ...
   {label => 'Магазин', lat => 55.809418, lon => 37.464657, fake => 0},
 ]);

В этом случае процедура синхронизирует все записи, но не вернёт никакого значения (по аналогии с wish table_data).

Clone this wiki locally