Работа с БД в Drupal 7 - урок 8 - Запросы вставки (INSERT INTO)
Запросы вставки всегда должны использовать конструктор запросов. Некоторые БД требуют специальных обработчиков для LOB (Large OBject, такие как текст в MySQL) и BLOB (Binary Large OBject) полей, так что уровень абстракции необходим для индивидуальных драйверов БД для реализации подобных обработчиков.
Запросы вставки начинаются с использования функции db_insert():
<?php $query = db_insert('node', $options); ?>
Запрос вставки создает объект-запрос который вставляет одну или больше записей в таблицу node. Заметьте что не требуется использовать фигурные скобки, конструктор запросов сам обрабатывает имена таблиц.
Запрос вставки использует свободный (fluent) API. Это значит что все методы (включая execute()) возвращают объект на себя позволяя использовать метод сцепления.
Запросы вставки поддерживают большое число различных паттернов для различных целей. В первую очередь рабочий поток описывает поля, в которые запрос вставляет данные, описывает значения запроса которые будут вставлены. Наиболее часто используемые паттерны описаны ниже.
Сокращенная форма (Compact form)
Предпочтительная форма для большинства запросов в компактной форме:
<?php $nid = db_insert('node') ->fields(array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, )) ->execute(); ?>
Этот запрос будет эквивалентен следующему:
INSERT INTO {node} (title, uid, created) VALUES ('Example', 1, 1221717405);
Описанный выше сниппет связывает ключи и вставляемые данные.
<?php db_insert('node') ?>
Эта строка создает новый объект-запрос для таблицы node.
<?php ->fields(array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, )) ?>
Метод fields() принимает несколько параметров, однако один ассоциативный массив общий в большинстве случаев. Ключи массива это колонки таблицы в которые нужно вставить значения, а значение массива это данные которые будут вставлены. Так что результатом будет запрос вставки для описанной таблицы.
<?php ->execute(); ?>
В отличие от других методов вставки объект-запрос, который возвращает объект-запрос на себя, execute() возвращает значение поля auto-increment которое было использование для вставки данных. Для таблицы node это будет значение nid. Если где-то нет поля auto-increment значение возвращаемое execute() будет undefined (неопределенно) и не следует ему доверять. В обычных случаях это предпочтительный вариант запросов вставки.
Упрощенная форма (Degenerate form)
<?php $nid = db_insert('node') ->fields(array('title', 'uid', 'created')) ->values(array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, )) ->execute(); ?>
Этот запрос эквивалентен следующему и будет иметь тот же результат:
<?php ->fields(array('title', 'uid', 'created')) ?>
Когда fields() вызван с индексированным массивом вместо ассоциативного, это устанавливает поля (колонки БД) которые будут использованы в запросе без каких-либо значений для них. Это нужно для multi-insert запросов.
<?php ->values(array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, )) ?>
Метод в описывает ассоциативный массив имен полей для значений вставляемых в эти поля. Метод values() может также принимать индексированный массив. Если используется индексированный массив, то порядок значений должен совпадать с порядком полей в методе fields(). Если используется ассоциативный массив, то порядок не имеет значения. Главное в ассоциативном массиве это его читаемость. Индексируемые массивы в запросах вставки редко используются, так как compact form более предпочтительная форма. В большинстве случаев причина разделения fields() и values() это multi-insert запрос.
Запрос множественной вставки (Multi-insert form)
Объект-запрос вставки может также принимать набор множественных значений. Так что values() может быть вызван множество раз в порядке очереди для нескольких вставок сразу. Каждый раз когда происходит вызов, это достигается за счет совместимости с БД через api. В большинстве БД множественные вставки будут выполнены вместе внутри одной транзакции для большей скорости выполнения запроса. В MySQL следующий синтаксис множественного запроса.
<?php $values = array( array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, ), array( 'title' => 'Example 2', 'uid' => 1, 'created' => REQUEST_TIME, ), array( 'title' => 'Example 3', 'uid' => 2, 'created' => REQUEST_TIME, ), ); $query = db_insert('node')->fields(array('title', 'uid', 'created')); foreach ($values as $record) { $query->values($record); } $query->execute(); ?>
Код выше приводит пример исполнения трех запросов вставки вместе в одном блоке с использованием эффективного метода особого использования драйвера БД. Заметьте что мы сохранили объект-запрос в переменную так чтобы мы могли вызвать цикл для $values и вызывать метод values() повторно.
В случае разделения values() и fields() как в вышеуказанном примере это эквивалентно трем запросам:
INSERT INTO {node} (title, uid, created) VALUES ('Example', 1, 1221717405); INSERT INTO {node} (title, uid, created) VALUES ('Example2', 1, 1221717405); INSERT INTO {node} (title, uid, created) VALUES ('Example3', 2, 1221717405);
Заметьте что в множественном запросе возвращаемое значение от execute() это undefined и этому значению не стоит доверять, так как это значение различное для различных драйверов БД.
Вставка основанная на результате запроса выборки (Сводная таблица)
Если вы хотите заполнить таблицу результатами из других таблиц (сводная таблица), вам нужно использовать SELECT для таблиц источников, обрабатывать их на PHP и вставлять в новую таблицу или вы можете использовать INSERT INTO ... SELECT FROM запрос для каждой записи возвращаемой из SELECT и вставлять для каждого INSERT.
В нашем примере нужно сделать таблицу "mytable", в которой все nid и username для всех нод в системе.
Drupal 6
<?php db_query('INSERT INTO {mytable} (nid, name) SELECT n.nid, u.name FROM {node} n LEFT JOIN {users} u on n.uid = u.uid WHERE n.type = "%s"', array ('page')); ?>
Drupal 7
<?php // Build the SELECT query. $query = db_select('node', 'n'); // Join to the users table. $query->join('users', 'u', 'n.uid = u.uid'); // Add the fields we want. $query->addField('n','nid'); $query->addField('u','name'); // Add a condition to only get page nodes. $query->condition('type', 'page'); // Perform the insert. db_insert('mytable') ->from($query) ->execute(); ?>
Значения по умолчанию (Default values)
При нормальных условиях, если вы не определите значение даваемое полю и значение по умолчанию определено через описание таблицы, тогда БД будет в тихом режиме вставлять значение умолчанию. В некоторых случаях, однако, вам нужно явно определить для БД использование значений по умолчанию. Это относится к тем случаям, когда вы хотите использовать все значения по умолчанию для всех записей. Явно сказать БД использовать значения по умолчанию можно с помощью метода useDefaults().
<?php $query->useDefaults(array('field1', 'field2')); ?>
Этот кода заставляет запрос использовать значения по умолчанию для полей field1 и field2. Заметьте что ошибочное определение одинаковых полей в useDefaults() и fields() или values() вызовет ошибку.