Drupal 7 Cheat Sheet: The Database

This is a quick post while it's fresh in my head, regarding porting your contributed modules to the Drupal 7 API. This post specifically focusses on database manipulation and provides the like-for-like changes. If anything here is wrong, or could be done better, please let me know!

First up, individual results:

<?php
/*
* Remember this?
*/
$value = db_result(db_query("SELECT some_field FROM {some_table}"));

/*
* Forget it! It now looks like this:
*/
$value = db_query("SELECT some_field FROM {some_table}")->fetchField();
?>

Selects still look pretty much the same, at first glance, but wait:

<?php
/*
* Let's fetch a database object in Drupal 6:
*/
$result = db_query("SELECT some_field FROM {some_table} WHERE some_other_field = %d", $some_var);
while (
$row = db_fetch_object($result)) {
 
// Loop through your query results and do some stuff.
}

/*
* In Drupal 7 there is no db_fetch_object() or db_fetch_array():
*/
$result = db_query("SELECT some_field FROM {some_table} WHERE some_other_field = :some_other_field", array(':some_other_field' => $some_var));
foreach (
$result as $row) {
 
// Loop through your query results and do some stuff.
}
?>

Deletes and updates now look quite different. You don't use db_query() at all any more for those types of SQL query. Each one has its own query building function:

<?php
/*
* A delete query in Drupal 7:
*/
db_delete('some_table')
  ->
condition('some_field', $some_var)
  ->
execute();

/*
* An update query in Drupal 7:
*/
db_update('some_table')
  ->
fields(
    array(
     
'some_field' => $some_var,
     
'some_other_field' => $some_other_var,
    )
  )
  ->
condition('some_identifying_field', $some_id_var)
  ->
execute();
?>

You should already be using drupal_write_record() for inserts anyway, and it has not changed, as far as I can tell.

Good news is hook_schema() and the related functions don't seem to have changed at all, so many of you won't need to touch installation scripts, unless you need to manipulate data as part of the update process, of course.

And that's that for now. Hope it's useful.

dynamic ones too!

Or you can use the dynamic version, something like:

<?php
  $query
= db_select('file', 'f');
 
$query->join('image', 'i', 'f.fid = i.fid');
 
$query->condition('i.nid', $id, '=')
    ->
fields('f')
    ->
fields('i');
 
$result = $query->execute();
?>

Oh, this looks different, indeed ...

Oh, this really looks different indeed. Thanks a lot for this explanation.

Please add to the Examples module

The Example Module has a dbtng_example.module in it, but it mostly only has the easy things in it. Patches are welcome to demonstrate more extensive and complex examples. There are even a couple of issues open about these.

D7 database seems easy when first look at it... but then doing the real-life things you need to do sometimes gets a little more challenging.

similar tutorial

small correction

<?php
$result
= db_query("SELECT some_field FROM {some_table} WHERE some_other_field = %d", $some_var);
?>

should be

<?php
$result
= db_query("SELECT some_field FROM {some_table} WHERE some_other_field = :some_other_field", array(':some_other_field' => $some_var));
?>

Good catch

Haha, see what I did there? Good "catch"? *ahem*
I'll get my coat.

Updated! Thanks! =)

What about more complex queries?

A while back I ran into a problem in D6 with the schema module - it was throwing errors because I had used a date field and this isn't supported in the Drupal schema API.

I contributed a patch and now date and timestamp types are supported.

However there are plenty of types that are still not supported - from boolean to polygon.

I'm concerned that the D7 move will lock out more advanced database use.

Your examples above make me wonder how to represent multi table updates

I'm working on one right now

<?php
    db_query
('update shorturl_link, (select count(*) as c, url_id from shorturl_access group by url_id) as access_count set clicks =access_count.c where access_count.url_id=shorturl_link.lid');
?>

This does the heavy lifting of data aggregation in a cron job - it does what I need in a single query.

My 'table' field is a join on a derived table - not a simple string.

I tried to look up the Database class being used - but the api module doesn't seem to be able to cope with documenting class structures yet

The syntax of the new API looks nice, and your examples are helpful.

Still possible

I think you *can* use db_query() still for updates and deletes, but you shouldn't unless you have to. That's the impression I get, anyway.

class DatabaseConnection extends PDO

After a bit of a struggle* I've found the docs I wanted

http://api.drupal.org/api/drupal/includes--database--database.inc/7/source

<?php
/**
* Base Database API class.
*
* This class provides a Drupal-specific extension of the PDO database
* abstraction class in PHP. Every database driver implementation must provide a
* concrete implementation of it to support special handling required by that
* database.
*
* @see <a href="http://php.net/manual/en/book.pdo.php
" title="http://php.net/manual/en/book.pdo.php
">http://php.net/manual/en/book.pdo.php
</a> */
abstract class DatabaseConnection extends PDO {
?>

db_query calls pdo->db_query

so yes you can use this where required to run more complex updates etc.

* the api module doesn't tell you about the class hierarchy and, I have in the past managed to get phpdoc to run on drupal code - but can't get it working right now !

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote>
  • Lines and paragraphs break automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.