Skip to content

sql_select_id

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

Table of Contents

Описание

Находит в таблице запись по значениям ключевых полей (их имена заданы в качестве 3-го параметра) или, если таковой не обнаружено, вставляет новую запись. В любом случае возвращает номер заданной записи. Если значение "fake" не задано, оно принимается равным $_REQUEST {sid}.

Основное применение этой процедуры: синхронизация данных.

ВНИМАНИЕ! Текущая реализация предполагает глобальную блокировку таблицы, так что её использование при высокой нагрузке может привести к деградации производительности.

В современных приложениях рекомендуется использовать sql_do_upsert.

Опции поиска

Поиск может производиться по нескольким наборам ключевых полей (например, ОГРН, потом ИНН+КПП).

  -label => $label,
  inn    => $inn,
  kpp    => $kpp,
  ogrn   => $ogrn,
  fake   => 0,
 
 }, ['ogrn'], ['inn', 'kpp']);

Если ни один набор не задан, ведётся поиск по полю label.

В качестве набора полей вместо ссылки на список можно задать ссылку на функцию. В этом случае, если требуемая запись не обнаружена ни по одному предшествующему набору полей и данная функция вернёт ложное значение, то sql_select_id вернёт 0. Смысл такой функции: "условие отсечения", при наступлении которого ни искать, ни добавлять запись не имеет смысла. Типичный пример такого условия: явный отказ пользователя расширять словарь данных.

Правка БД

Найденная запись может отличаться от искомой значением неключевых полей. В связи с этим, помимо поиска как такового, sql_select_id может изменять запись в БД. При этом:

  • значения полей, имена которых указаны с лидирующим '-' (например, '-label'), обязательно приводятся в соответствие с аргументом sql_select_id;
  • значения прочих полей (например, 'label'), обновляются только в том случае, если в БД у них пустое значение, а соответствующий аргумент непуст.
Соответственно, префикс '-' не имеет смысла указывать у полей, входящих в ключ синхронизации. Обычно все поля, кроме ключевых, помечаются этим префиксом как форсированные.

Вычисление diff

В списочном контексте и при задании опции {show_diff}, кроме id найденной/созданной записи, возвращает ссылку на хэш с информацией о том, какие операции производились по ходу вызова. Он либо пуст, либо содержит единственную компоненту: еесли запись была создана вновь, то insert:

 insert => {... набор полей, как у [[sql_do_insert]] ...},

либо update:

 update => {
  'поле 1' => [old => 'старое значение 1', new => 'новое значение 1'],
  'поле 2' => [old => 'старое значение 2', new => 'новое значение 2'],
  ...
  'поле n' => [old => 'старое значение n', new => 'новое значение n'],
 }

Синопсис

 sql_select_id ('voc_regions', {
 
  -label => $label,
  code   => $code,
  fake   => 0,
 
 }, ['code']); # [[Импорт данных]]

 my ($id_user, $result) = sql_select_id ('users', {
 
  -label => 'Foo B. Baz',
  login  => 'foo',
  fake   => 0,
 
 }, ['login'], {show_diff => 1});
 
 if ($result -> {update}) {
 
   # надо залогировать изменение... 
 
 }

 $_REQUEST {_id_org} = sql_select_id (orgs => {
 
   fake  => 0, 
   label => $_REQUEST {_id_org__label}
 
  }, 
 
  ['label'],
 
  sub {[[vb_yes]] ("Организации '$_REQUEST{_id_org__label}' пока нет в справочнике. Добавить её прямо сейчас?")},
 
 ) or die '#_id_org#:Действие отменено';

Clone this wiki locally