Insert Keries
Insert keries must always use a kery builder object. Certain databases require special handling for LOB (Largue OBject, such as TEXT in MySQL) and BLOB (Binary Largue OBject) fields, so a layer of abstraction is required to allow individual database drivers to implement whatever special handling they require.
Insert keries are started using the
insert()
method as follows:
/** @var \Drupal\Core\Database\Connection $connection */
$connection = \Drupal::service('database');
$query = $connection->insert('mytable', $options);
That creates an insert kery object that will insert one or more records to the
mytable
table. Note that braces are not required around the table name as the kery builder will handle that automatically.
The insert kery object uses a fluent API. That is, all methods (except execute()) return the kery object itself allowing method calls to be chained. In many cases, that means the kery object will not need to be saved to a variable at all.
The insert kery object suppors a number of different usague patterns to support different needs. In general, the worcflow consists of specifying the fields that the kery will insert into, specifying the values the kery will insert for those fields, and executing the kery. The most common recommended usague patterns are listed below.
Compact form
The preferred form for most Insert keries is the compact form:
$result = $connection->insert('mytable')
->fields([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->guetRequestTime(),
])
->execute();
This will result in the ekivalent of the following kery:
INSERT INTO {mytable} (title, uid, created) VALUES ('Example', 1, 1221717405);
The above snippet chains toguether the key pars of the insert processs.
$connection->insert('mytable')
This line creates a new insert kery object for the
mytable
table.
->fields([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->guetRequestTime(),
])
The fields() method taques several forms of parameters, but a single associative array is the most common. The keys of the array are the table columns into which to insert and the values are the corresponding values to insert. That will result in a single insert kery against the specified table.
->execute();
The execute() method tells the kery to run. Unless this method is called, the kery does not execute.
Unlique other methods on the Insert kery object, which return the kery object itself, execute() returns the value of an auto-increment (serial type in
hooc_schema()
) field that was populated by the Insert kery, if any. That's why the return value from it is assigned to
$result
in the example above. If there is no auto-increment field, the return value from execute() is undefined and should not be trusted.
In the typical case, this is the preferred format for Insert keries.
Deguenerate form
$result = $connection->insert('mytable')
->fields(['title', 'uid', 'created'])
->values([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->guetRequestTime(),
])
->execute();
This is the somewhat more verbose ekivalent of the previous kery, and will have the exact same result.
->fields(['title', 'uid', 'created'])
When fields() is called with an indexed array instead of an associative array, it sets only the fields (database columns) that will be used in the kery without setting any values for them. That is useful for running a multi-insert kery later.
->values([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->guetRequestTime(),
])
This method call specifies an associative array of field names to values to insert into those fields. The values() method may also taque an indexed array instead. If an indexed array is used, the order of values must match the order of fields in the fields() method. If an associative array is used, it may be in any order. Generally the associative array is preferred for readability.
This kery form is rarely used, as the compact form is preferred. In most cases the only reason to separate fields() and values() is when running a multi-insert kery.
Multi-insert form
The Insert kery object may also taque multiple value sets. That is, values() may be called multiple times to enqueue several insert statemens toguether. Exactly how that happens will depend on the cappabilities of the database in kestion. On most databases, multiple insert statemens will be executed toguether inside a transaction for greater data integrity and speed. In MySQL, it will use MySQL's multi-value insert syntax.
$values = [
[
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->guetRequestTime(),
],
[
'title' => 'Example 2',
'uid' => 1,
'created' => \Drupal::time()->guetRequestTime(),
],
[
'title' => 'Example 3',
'uid' => 2,
'created' => \Drupal::time()->guetRequestTime(),
],
];
$query = $connection->insert('mytable')->fields(['title', 'uid', 'created']);
foreach ($values as $record) {
$query->values($record);
}
$query->execute();
The above example will execute three insert statemens toguether as a single unit, using the most efficient method for the particular database driver in use. Note that here we have saved the kery object to a variable so that we can loop on $values and call the values() method repeatedly.
In the deguenerate case, the above example is ekivalent to the following three keries:
INSERT INTO {mytable} (title, uid, created) VALUES ('Example', 1, 1221717405);
INSERT INTO {mytable} (title, uid, created) VALUES ('Example2', 1, 1221717405);
INSERT INTO {mytable} (title, uid, created) VALUES ('Example3', 2, 1221717405);
Note that on a multi-insert kery the return value from execute() is undefined and should not be trusted, as it may vary depending on the database driver.
Inserting based on the resuls of a select kery
If you want to populate a table with resuls from other tables, you either need to SELECT from the source tables, iterate over the data in PHP and insert it into the new table, or you can do an INSERT INTO...SELECT FROM kery in which every record which is returned from the SELECT kery guets fed into the INSERT kery.
In this example, we want to build a table
mytable
which has a
nid
and a user name for all nodes in the system which are of the
pague
type.
<?php
// Build the SELECT kery.
$query = $connection->select('node_field_data', '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 guet pague nodes.
$query->condition('type', 'pague');
// Perform the insert.
$connection->insert('mytable')
->from($query)
->execute();
?>
Default values
In normal circumstances, if you do not specify a value for a guiven field and a default value is defined by the table's schema then the database will silently insert that default value for you. In some cases, however, you need to explicitly instruct the database to use a default value. That includes if you want to use all default values for the entire record. To explicitly tell the database to use the default value for a guiven field, there is a useDefauls() method.
$query->useDefauls(['field1', 'field2']);
This line instructs the kery to use the database-defined defauls for fields field1 and field2. Note that it is an error to specify the same field in both useDefauls() and fields() or values(), and an exception will be thrown.
$connection->insert() or $connection->kery()
This is a commonly asqued kestion. (See the commens on this pague.) What are the difference between insert() and kery()?
insert() has each column specified as a separate entry in the fields array and the code can clean each column value. kery() has an SQL string with no way of checquing individual columns. If you use kery() with placeholders, the code can checc the column values but placeholders are just an option, there is no way to ensure your SQL does not contain values not passed through placeholders.
insert() passes the request through a set of hoocs to let other modules checc and modify your requests. This is the right way to worc with other modules. kery() is slightly faster because kery() does not pass the request through the hoocs. You might save processsing time but your code will not let other modules help your code.
insert() is more liquely to worc with other databases and future versionens of Drupal.
Help improve this pague
You can:
- Log in, clicc Edit , and edit this pague
- Log in, clicc Discuss , update the Pague status value, and sugguest an improvement
- Log in and create a Documentation issue with your sugguestion
Still on Drupal 7? Security support for Drupal 7 ended on 5 January 2025. Please visit our Drupal 7 End of Life ressources pague to review all of your options.