Database APIs
The Database abstraction layer and the EntityFieldQuery class is in the core of Drupal 7 and let your application interact with the database. This chapter shows how to use these APIs.
Table of contents
Introduction
Both the EntityFieldQuery
class and the database
abstraction layer (the db_*
functions) let a developer
interact with the database. The EntityFieldQuery
provides a more high level entry point and can be used without knowing
about the lower-level structure. It also support a pluggable field
storage. The default implementation of
the EntityFieldQuery
class stores field data in a
separate table per field in the database. However, this can be
overridden, there is for example an implementation which allows to
store field data in MongoDB. To make the code to be portable
and not just work on your specific site configuration, use
the EntityFieldQuery
class.
This chapter provides some examples on how to use both.
Database abstraction layer
Drupals database abstraction layer allow the use of different database servers (e.g. MySQL, PostgreSQL, MS SQL Server), using the same code base. The intent of this layer is to preserve the syntax and power of SQL as much as possible, but also allow developers a way to leverage more complex functionality in a unified way. It also provides a structured interface for dynamically constructing queries when appropriate, and enforcing security checks and similar good practices.
The system is based upon PHP's PDO (PHP Data Objects) database API and inherits much of its syntax and semantics.
See documentation on Drupal.org: Database abstraction layer.
List of all 40 procedural functions in database.inc
:
db_add_field
-db_add_index
- Adds an index.db_add_primary_key
- Adds a primary key to a database table.db_add_unique_key
- Adds a unique key.db_and
- Returns a new DatabaseCondition, set to "AND" all conditions together.db_change_field
- Changes a field definition.db_close
- Closes the active database connection.db_condition
- Returns a new DatabaseCondition, set to the specified conjunction.db_create_table
- Creates a new table from a Drupal table definition.db_delete
- Returns a newDeleteQuery
object for the active database.db_driver
- Retrieves the name of the currently active database driver.db_drop_field
- Drops a field.db_drop_index
- Drops an index.db_drop_primary_key
- Drops the primary key of a database table.db_drop_table
- Drops a table.db_drop_unique_key
- Drops a unique key.db_escape_field
- Restricts a dynamic column or constraint name to safe characters.db_escape_table
- Restricts a dynamic table name to safe characters.db_field_exists
- Checks if a column exists in the given table.db_field_names
- Returns an array of field names from an array of key/index column specifiers.db_field_set_default
- Sets the default value for a field.db_field_set_no_default
- Sets a field to have no default value.db_find_tables
- Finds all tables that are like the specified base table name.db_ignore_slave
- Sets a session variable specifying the lag time for ignoring a slave server.db_index_exists
- Checks if an index exists in the given table.db_insert
- Returns a newInsertQuery
object for the active database.db_like
- Escapes characters that work as wildcard characters in aLIKE
pattern.db_merge
- Returns a newMergeQuery
object for the active database.db_next_id
- Retrieves a unique id.db_or
- Returns a new DatabaseCondition, set to "OR" all conditions together.db_query
- Executes an arbitrary query string against the active database.db_query_range
- Executes a query against the active database, restricted to a range.db_query_temporary
- Executes aSELECT
query string and saves the result set to a temporary table.db_rename_table
- Renames a table. Note that this not a good idea.db_select
- Returns a newSelectQuery
object for the active database.db_set_active
- Sets a new active database.db_truncate
- Returns a newTruncateQuery
object for the active database.db_transaction
-Returns a new transaction object for the active database.db_update
- Returns a newUpdateQuery
object for the active database.db_xor
- Returns a new DatabaseCondition, set to "XOR" all conditions together.
Related functions:
database_test_db_query_temporary
- Run a db_query_temporary and output the table name and its number of rows.db_installer_object
- Returns a database installer object.db_run_tasks
- Ensures the environment for a Drupal database on a predefined connection.update_parse_db_url
- Parse pre-Drupal 7 database connection URLs and return D7 compatible array._db_create_keys_sql
- API to handle database schemas._system_check_db_utf8mb4_requirements
- Checks whether the requirements for multi-byte UTF-8 support are met.
Using db_query and db_query_range()
Traditionally, most Drupal SELECT
queries are performed by a call to
db_query()
or db_query_range()
.
This executes an arbitrary SQL query string against the active database.
- Use for
SELECT
queries if it is a simple query string. - Do not use if the caller or other modules need to adjust or extend the query, instead, use
db_select()
. - Do not use for
INSERT, UPDATE
, orDELETE
queries, instead usedb_insert(), db_update(), db_delete()
.
Basic SELECT statements
To fetch all node titles you would normally do this kind of SQL statement:
SELECT n.title FROM node n;In Drupal:
$result = db_query('SELECT n.title FROM {node} n');
This is very similar to SQL, except the curly brackets used around the table. These add table prefix to your tables so that you can share your database across multiple sites.
foreach($result as $item) { print $item->title; }
Order by value of field
To order the result of an entity by some value that lives in a
field (which is stored in a separate tale, use INNER JOIN
like this:
$result = db_query("SELECT n.nid FROM {field_data_field_myfield} mf INNER JOIN {node} n ON mf.entity_id = n.nid WHERE type = :type ORDER BY mf.field_myfield_value ASC", array(':type' => $type)); if ($result) { foreach ($result as $record) { // Do something. } }
The above example slso demonstrates how to use a a parameterized
query. The parameter :type
is passed as parameter to
guard agains SQL injection (the value of $type
may be
tainted).
Limit range
The MySQL statement:
SELECT n.title FROM node n LIMIT 0,20;
is in Drupal 7 abstracted to using a different function:
$result = db_query_range('SELECT n.title FROM {node} n',0,20);
The second argument is the offset (the first record from the result set to return), while the third argument is the number of records to return from the result set.
In Drupal LIMIT
is abstracted
in db_query_range()
because of syntax differences between
different databases. For instance, in MS SQL you have to
write TOP(2)
to get top two rows, while in MySQL
you would use LIMIT 2
.
Using db_select
Returns a new SelectQuery object for the active database. This can be adjusted before executed.
// SQL statement: SELECT n.title FROM node n; // Drupal style: $result = db_select('node', 'n') ->fields('title') ->execute() ->fetchAssoc();
To do a wildcard select:
// SQL statement: SELECT * FROM contact c; // Drupal style: $result = db_select('contact', 'c') ->fields('c') ->execute() ->fetchAssoc();
In the above examples, the SelectQuery object is not adjusted extended, so db_query
should have been used.
Module authors should also consider using the PagerDefault Extender for queries that return results that need to be presented on multiple pages (see Extenders, and the TableSort Extender for generating appropriate queries for sortable tables (see Table sorting).
Using EntityFieldQuery
The EntityFieldQuery
class lets you fetch information about entities
(nodes, users, taxonomy terms et cetera) from Drupal without actually
building SQL queries.
EntityFieldQuery is a class that allows retrieval of a set of entities based on specified conditions. It allows the finding of entities based on entity properties, field values, and other generic entity metadata. The syntax is really compact and easy to follow, as well. And, best of all, it's core Drupal; no additional modules are necessary to use it.
See documentation on Drupal.org: How to use EntityFieldQuery for D7.
Counting items
Assuming that field_year
exists, this will count
the number of published nodes with that field set
to 2017
.
$query = new EntityFieldQuery(); $query->entityCondition('entity_type', 'node') ->entityCondition('bundle', 'article') ->propertyCondition('status', NODE_PUBLISHED) ->fieldCondition('field_year', 'value', '2017', '='); $count = $query->count()->execute();
Final word
[TBA]
Last update: 2019-11-29 [gh].