Skip to main content

Updating tables schema: hook_update_N() functions - modifyting a table

ref: http://drupal.org/node/150215

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;
}

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']);