Community Documentation

Updating tables: hook_update_N() functions

Last updated November 2, 2011. Created by snufkin on June 7, 2007.
Edited by fmitchell, drclaw, jhodgdon, kiamlaluno. Log in to edit this page.

As in previous versions of Drupal, you can update database tables for new versions using a hook_update_N() function.

Adding a new column (D6)

Suppose that mymodule adds a new column called 'newcol' to mytable1 in version 6.x-1.5. Prior to Schema API, you would:

  1. Add newcol to the CREATE TABLE statements in mymodule_install().
  2. Create a mymodule_update_N() function to add newcol to existing mytable1 tables with ALTER TABLE statements.

Using Schema API, you perform the same two steps:

  1. Add newcol to the table definition array in mymodule_schema() in mymodule.install.
  2. Create a mymodule_update_N() function to add newcol to existing mytable1 tables with the Schema API function db_add_field():

    <?php
    function mymodule_update_6100() {
     
    $ret = array();
     
    db_add_field($ret, 'mytable1', 'newcol', array('type' => 'int', 'not null' => TRUE));
      return
    $ret;
    }
    ?>

Adding a new column (D7)

Using Schema API, you perform the same two steps:

  1. Add newcol to the table definition array in mymodule_schema() in mymodule.install.
  2. Create a mymodule_update_N() function to add newcol to existing mytable1 tables with the Schema API function db_add_field():

    <?php
    function mymodule_update_7100() {
     
    $spec = array(
       
    'type' => 'varchar',
       
    'description' => "New Col",
       
    'length' => 20,
       
    'not null' => FALSE,
      );
     
    db_add_field( 'mytable1', 'newcol', $spec);
    }
    ?>

Adding a new column to a custom field (D7)

Using Field API, you've already created a new field and it works great. You want to add a new form element to that field.

The original schema, using hook_field_schema():

<?php
function mymodule_field_schema($field) {
  return array(
   
'columns' => array(
     
'fid' => array(
       
'description' => 'The {file_managed}.fid being referenced in this field.',
       
'type' => 'int',
       
'not null' => FALSE,
       
'unsigned' => TRUE,
      ),
     
'title' => array(
       
'description' => "Photo title text",
       
'type' => 'varchar',
       
'length' => 128,
       
'not null' => FALSE,
      ),
    ),
   
'indexes' => array(
     
'fid' => array('fid'),
    ),
   
'foreign keys' => array(
     
'fid' => array(
       
'table' => 'file_managed',
       
'columns' => array('fid' => 'fid'),
      ),
    ),
  );
}
?>

To add a new column, do the following two steps:

  1. Add newcol to the table definition array in mymodule_field_schema() in mymodule.install. When you do this, the field configuration is automatically updated as field_read_fields invokes the updated schema in the install file.
  2. Create a mymodule_update_N() function to add newcol to existing mytable1 tables with the Schema API function db_add_field(), but also add it to the revision table:

    <?php
    function mymodule_update_7100(&$sandbox) {
     
    $spec = array(
       
    'type' => 'varchar',
       
    'description' => "New Col",
       
    'length' => 20,
       
    'not null' => FALSE,
      );
     
    $data_table_name = 'field_data_field_myfield';
     
    $revision_table_name = 'field_revision_field_myfield';
     
    $field_name = 'field_myfield_newfield';

     
    db_add_field($data_table_name, $field_name, $spec);
     
    db_add_field($revision_table_name, $field_name, $spec);
    }
    ?>

Adding a new table

Similarly, suppose that for version 6.x-1.6 mymodule now needs a completely new table called mytable2. You perform the same two steps:

  1. Add the new table to mymodule_schema() in mymodule.install.
  2. Create a mymodule_update_N() function to create mytable 2 with the Schema API function db_create_table():

    <?php
    function mymodule_update_6101() {
     
    $schema['mytable2'] = array(
        
    // table definition array goes here
     
    );
     
    $ret = array();
     
    db_create_table($ret, 'mytable2', $schema['mytable2']);
      return
    $ret;
    }
    ?>

Adding keys

And as for adding a unique, or a primary key, one can now use dedicated API functions:

<?php
function mymodule_update_6102() {
 
$ret = array();
 
db_add_unique_key($ret, 'mytable2', 'mykey', array('field1', 'field2')); 
  return
$ret;
}
?>

<?php
/**
* Adding a primary key.
*/
function mymodule_update_6103() {
 
$ret = array();
 
db_add_primary_key($ret, 'mytable2', array('nid'));
  return
$ret;
}
?>

Important note: You may be tempted to pass a table definition from your own hook_schema function directly to db_create_table(). Please read why you cannot use hook_schema from within hook_update_N().

Updating a Table

This simple example shows how to change a modules weight using an sql UPDATE with the function update_sql()

<?php
function mymodule_update_6103() {
 
$ret = array();
 
// NOTE: update_sql() doesn't support %-substitution parameters
 
$ret[] = update_sql("UPDATE {system} SET weight = -1 WHERE name = 'mymodule'");
  return
$ret;
}
?>

Comments

Since I am developing privately and not for contribution, my 'VERSION' field in my module's .info file is either blank or unchanged when I update a module. I am actually using Subversive for eclipse PDT and therefore my info files version numbers never get updated. Thus, my hook_update_6001 was NOT being called by update.php.

If you are not changing Version numbers in your modules .info file, then you will not have hook_update_N called. Manually update your new version in .info and it will work fine. My Discovery. Hope it helps someone NOT spend and entire night trying to figure it out.

Uppercase in module name

And if this did not solve the problem yet, then it might be due to an uppercase letter in your module name. See Can Not Update Custom Module. Renaming the module seems to be the only way so far. Have fun.

Alternative ways for adding

Alternative ways for adding new columns/fields and tables. Since in most cases when adding new columns or tables the scheme hook should also be used the following will work and reduce duplicate code and errors.

Alternative way to adding a new column

function module_name_update_6100() {
  $ret = array();
 
  $table_name = 'name of table being updated';
  $field_name = 'name of new field';
  $table = drupal_get_schema_unprocessed('module_name', $table_name);
  db_add_field($ret, $table_name, $field_name, $table['fields'][$field_name]);
  return $ret;
}

Alternative way to adding a new table

function module_name_update_6100() {
  $res = array();

  $table_name = 'name of table being updated';
  $table = drupal_get_schema_unprocessed('module', $table_name);
  db_create_table($res, $table_name, $table);

  return $res;
}

Here is why you shouldn't do

Here is why you shouldn't do that!
http://drupal.org/node/150220

Error in adding a new table example

I was getting an error message when executing the update.php and it seems that the way to invoke the db_create_table method is not as mentioned in the example:
($ret, 'mytable2', $schema['mytable2']);
Apparently it should be like this:
$ret = db_create_table('mytable2', $schema['mytable2']);

Thanks.

This worked for me - wish I would have seen your post sooner. :)