Работа с БД в Drupal 7 - урок 11 - Запросы слияния (MERGE)

admin друпал drupal

Запросы слияния это специальный гибридный тип запросов. Хотя синтаксис для этих запросов был определен в SQL 2003, фактически нет БД поддерживающих этот синтаксис. Однако большинство БД предоставляют альтернативную реализацию использования специфического синтаксиса. Конструктор запросов слияния в Drupal абстрагирует концепцию слияния запроса в структуре объекта, так что объект может быть скомпилирован для каждой БД по разному с учетом ее специфики.

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

<?php
if (db_result(db_query("SELECT COUNT(*) FROM {example} WHERE id=:id", array(':id' => $id))->fetchField())) {
  // Run an update using WHERE id = $id
}
else {
  // Run an insert, inserting $id for id
}
?>

 

Реальная реализация делает запрос от БД к БД. Заметьте пока запросы слияния в концепции это атомарные операции, они могут или не могут быть по настоящему атомарными основываясь на реализации для специфической БД. Реализация MySQL - это атомарный запрос, например однако в указанном выше примере таковым не является.

Наиболее общий вид запроса слияния отображен ниже:

Просто сделай это

<?php
db_merge('example')
  ->key(array('name' => $name))
  ->fields(array(
      'field1' => $value1,
      'field2' => $value2,
  ))
  ->execute();
?>

 

В указанном выше примере, мы оперируем с таблицей "example". Мы описываем одно ключевое поле 'name, со значением $name. Также описываем массив значений для установки.

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

Установка условий

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

<?php
db_merge('example')
  ->key(array('name' => $name))
  ->fields(array(
      'field1' => $value1,
      'field2' => $value2,
  ))
  ->updateFields(array(
    'field1' => $alternate1,
  ))
  ->execute();
?>

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

<?php
db_merge('example')
  ->key(array('name' => $name))
  ->fields(array(
      'field1' => $value1,
      'field2' => $value2,
  ))
  ->expression('field1', 'field1 + :inc', array(':inc' => 1))
  ->execute();
?>

 

 

В этом примере, если запись уже существует, тогда field1 будет установлена с прибавлением 1. Это делается возможным для полезных "запросов счетчиков", когда вам необходимо приращивать некоторый счетчик каждый раз по пришествию какого-либо события. Однако если такой записи нет, то поля field1, field2 обновят свои значения. Заметьте что expression() может быть вызвано множество раз, однажды для каждого поля, чтобы установить выражение если запись уже существует. Первый параметр это поле, второй это фрагмент SQL показывающий выражение которое должно быть установлено и третий опциональный параметр это массив значений заменителей, которые должны быть вставлены в выражение.

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

Ограниченное обновление

<?php
db_merge('example')
  ->key(array('name' => $name))
  ->fields(array(
      'field1' => $value1,
      'field2' => $value2,
  ))
  ->updateExcept('field1')
  ->execute();
?>

Метод updateExcept() принимает или массив полей или серию полей как разделенные параметры. Поля описанные в updateExcept() не будут обработаны если запись уже существует. Так что, если запись name = $name уже существует тогда поле field2 будет установлено $value2 и field1 будет проигнорировано полностью и останется с текущим значением, однако если запись еще не существует, то оно будет установлено $value 1.

Приоритет

Приведенный выше API вполне позволяет определить запрос таким образом, что это не будет иметь смысл. Например если поле устанавливает игнорирование на оба поля и устанавливает выражение если запись существует. Для минимизации возможных ошибок, применяются следующие правила:

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

Заметьте что может быть возможным для определения запросов, что они будут не иметь смысла.

Добавить комментарий

Войти, используя Loginza Google Account Yandex Mail.ru Vkontakte Facebook

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.