Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

Запросы слияния merge

09/05/2020, by maria

Запросы слияния представляют собой особый тип гибридного запроса. Хотя синтаксис для них определен в спецификации SQL 2003, практически ни одна база данных не поддерживает стандартный синтаксис. Однако большинство из них предоставляют альтернативную реализацию с использованием синтаксиса, специфичного для базы данных. Построитель запросов слияния в Drupal абстрагирует концепцию запроса слияния в структурированный объект, который может быть скомпилирован с соответствующим синтаксисом для каждой базы данных. Их иногда называют запросами "UPSERT", комбинацией UPDATE и INSERT.

В общем смысле запрос на слияние - это сочетание запроса на вставку и запроса на обновление. Если данное условие выполнено, например, строка с заданным первичным ключом уже существует, выполняется запрос на обновление. Если нет, выполняется запрос на вставку. В наиболее распространенном случае это эквивалентно:

if ($connection->query("SELECT COUNT(*) FROM {example} WHERE id = :id", [':id' => $id])->fetchField()) {
  // Run an update using WHERE id = $id
}
else {
  // Run an insert, inserting $id for id 
}

Фактическая реализация сильно варьируется от базы данных к базе данных. Обратите внимание, что хотя запросы слияния концептуально являются атомарной операцией, они могут быть или не быть действительно атомарными в зависимости от реализации конкретной базы данных. Например, реализация MySQL - это отдельный атомарный запрос, но вырожденный случай (выше) - нет.

Наиболее распространенные идиомы для запросов Merge перечислены ниже.

Просто установите его

$connection->merge('example')
  ->key('name', $name)
  ->fields([
      'field1' => $value1,
      'field2' => $value2,
  ])
  ->execute();

В приведенном выше примере мы указываем запросу работать с таблицей «example». Затем мы указываем одно ключевое поле 'name' со значением $name. Затем мы указываем массив значений для установки.

Если уже существует строка, в которой поле «name» имеет значение $name, тогда поля field1 и field2 будут установлены на соответствующие значения в этой существующей строке. Если такой строки не существует, будет создана такая, в которой name имеет значение $ name, field1 имеет значение $value1, а field2 имеет значение $value2. Таким образом, в конце запроса конечный результат остается одинаковым независимо от того, существовала или нет строка.

Условный набор

В некоторых случаях может потребоваться установить значения по-разному в зависимости от того, существует ли уже запись, как определено полями key(). Есть два способа сделать это.

$connection->merge('example')
  ->insertFields([
      'field1' => $value1,
      'field2' => $value2,
  ])
  ->updateFields([
    'field1' => $alternate1,
  ])
  ->key('name', $name)
  ->execute();

Приведенный выше пример будет вести себя так же, как и первый, за исключением того, что если запись уже существует и мы ее обновляем, для field1 будет установлено значение $alternate1 вместо $value1, и на field2 это не повлияет. Метод updateFields() принимает либо один ассоциативный массив значений, либо два параллельных числовых массива, одно из полей, одно из значений, которые должны быть в том же порядке.

$connection->merge('example')
  ->key('name', $name)
  ->fields([
      'field1' => $value1,
      'field2' => $value2,
  ])
  ->expression('field1', 'field1 + :inc', [':inc' => 1])
  ->execute();

В этом примере, если запись уже существует, для field1 будет установлено ее текущее значение плюс 1. Это делает ее очень полезной для «встречных запросов», когда вы хотите увеличивать некоторый счетчик в базе данных каждый раз, когда происходит определенное событие. field2 по-прежнему будет иметь одинаковое значение независимо от того, существует запись или нет.

Обратите внимание, что expression() может вызываться несколько раз, по одному разу для каждого поля, которое должно быть установлено в выражение, если запись уже существует. Первый параметр - это поле, второй - фрагмент SQL, указывающий на выражение, которому должно быть задано поле, а необязательный третий параметр - это массив значений заполнителей для вставки в выражение.

Также не требуется, чтобы поле, используемое в expression(), уже присутствовало в fields().

Учитывая приведенный выше API, вполне возможно определить запросы, которые не имеют логического смысла, скажем, если для поля установлено, что оба игнорируются и устанавливаются в выражение, если запись уже существует. Чтобы свести к минимуму возможные ошибки, применяются следующие правила:

  • Если для поля установлено expression(), оно имеет приоритет над updateFields().
  • Если значения указаны в updateFields(), только эти поля будут изменены, если запись уже существует. Поля, не указанные в updateFields(), не будут затронуты.

Обратите внимание, что все еще возможно определить запросы, которые не имеют смысла. Разработчик должен убедиться, что бессмысленный запрос не указан, поскольку поведение в этом случае не определено.

Source URL:

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.