8.3.x database.api.php hook_schema()
8.0.x database.api.php hook_schema()
8.1.x database.api.php hook_schema()
8.2.x database.api.php hook_schema()
8.4.x database.api.php hook_schema()
6.x install.php hook_schema()
7.x system.api.php hook_schema()

Define the current version of the database schema.

A Drupal schema definition is an array structure representing one or more tables and their related keys and indexes. A schema is defined by hook_schema() which must live in your module's .install file.

This hook is called at install and uninstall time, and in the latter case, it cannot rely on the .module file being loaded or hooks being known. If the .module file is needed, it may be loaded with drupal_load().

The tables declared by this hook will be automatically created when the module is first enabled, and removed when the module is uninstalled. This happens before hook_install() is invoked, and after hook_uninstall() is invoked, respectively.

By declaring the tables used by your module via an implementation of hook_schema(), these tables will be available on all supported database engines. You don't have to deal with the different SQL dialects for table creation and alteration of the supported database engines.

See the Schema API Handbook at http://drupal.org/node/146843 for details on schema definition structures. Note that foreign key definitions are for documentation purposes only; foreign keys are not created in the database, nor are they enforced by Drupal.

Return value

array A schema definition structure array. For each element of the array, the key is a table name and the value is a table structure definition.

See also


Related topics

45 functions implement hook_schema()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

aggregator_schema in modules/aggregator/aggregator.install
Implements hook_schema().
block_schema in modules/block/block.install
Implements hook_schema().
book_schema in modules/book/book.install
Implements hook_schema().
comment_schema in modules/comment/comment.install
Implements hook_schema().
contact_schema in modules/contact/contact.install
Implements hook_schema().

... See full list

2 invocations of hook_schema()
drupal_get_complete_schema in includes/bootstrap.inc
Gets the whole database schema.
drupal_get_schema_unprocessed in includes/common.inc
Returns the unprocessed and unaltered version of a module's schema.


modules/system/system.api.php, line 3221
Hooks provided by Drupal core and the System module.


function hook_schema() {
  $schema['node'] = array(
    // Example (partial) specification for table "node".
    'description' => 'The base table for nodes.',
    'fields' => array(
      'nid' => array(
        'description' => 'The primary identifier for a node.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      'vid' => array(
        'description' => 'The current {node_revision}.vid version identifier.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      'type' => array(
        'description' => 'The {node_type} of this node.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      'title' => array(
        'description' => 'The title of this node, always treated as non-markup plain text.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
    'indexes' => array(
      'node_changed' => array('changed'),
      'node_created' => array('created'),
    'unique keys' => array(
      'nid_vid' => array('nid', 'vid'),
      'vid' => array('vid'),
    // For documentation purposes only; foreign keys are not created in the
    // database.
    'foreign keys' => array(
      'node_revision' => array(
        'table' => 'node_revision',
        'columns' => array('vid' => 'vid'),
      'node_author' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
    'primary key' => array('nid'),
  return $schema;


markross’s picture

Database table is automatically created based on schema during module installation so no need to call drupal_install_schema() from hook_install() any more.

See here http://drupal.org/node/224333#install-schema

mlncn’s picture

It is somehow not mentioned anywhere here, but it exists: http://api.drupal.org/hook_schema_alter

markie’s picture

styusuf’s picture

If I have multiple databases on my drupal site, and I want to create the table in a separate database from my default drupal database, do I just run the function db_set_active line code(in the link above) before the hook_schema function? Would I have to run the the same db_set_active function to switch back to my default database after the hook_schema function. I just want to make sure I don't end up with data complications with my databases. If you don't understand my question, let me know and I can rephrase it. Thanks in advance!

renegaed’s picture

I have found that if you update hook_schema() while your module is enabled there seems to be an issue getting Drupal to generate your tables even after disabling and enabling your module. To get around this:

1. disable the module
2. uninstall the module (via the modules page)
3. enable the module

Your updated schema should now be reflected in the database. Hope this helps someone because I was scratching my head for a while at this.

Garrett Albright’s picture

Merely disabling a module is not a destructive action, as (unless it was coded improperly) it will not delete the database tables associated with the module, nor will it delete any site-wide variables associated with it. This is so that you can disable a module, then enable it, and still have all your data intact. Having to completely uninstall a module in order to nuke its tables is proper behavior.

If you're a developer wanting to test that your schema works correctly, you may find it handy to use Drush to disable, uninstall, then reinstall your module in one go:

drush dis my_module -y; drush pm-uninstall my_module -y; drush en my_module -y
jojonaloha’s picture

Even quicker if you have devel installed you can use the devel-reinstall (dre for short) command.

drush dre my_module -y
pal4life’s picture

Thanks for this , this is so much helpful .

aguchoca’s picture

It works but partially.

Id does disable and uninstall, but it doesnt not delete the TABLES so when it does the reinstallation will give you an error.

joegl’s picture

Thanks this is extremely helpful! I was wondering why when I added a schema to a module I developed it wasn't being created.

rashidkhan’s picture

drupal_install_schema is not needed to create tables inside the hook_schema for a module. To confirm it, I tried only hook_schema inside the .install file and it worked.

euk’s picture

It is worth mentioning that foreign keys definition is just for information, and is not supported in core.
For reference: https://www.drupal.org/node/911352#comment-9897671.

arpas’s picture

I can't use table name 'order'. Probably this was because word 'order' is MySQL reserved and can't be used as table name and drupal end with multiple sql errors. Strange situation. If module is installed with errors I can't properly uninstall. Tried multiple times while found my mistake.

shahbaj’s picture

can someone please explain me this
'indexes' => array(
'node_changed' => array('changed'),
'node_created' => array('created'),

kingandy’s picture

The array describes two separate indexes on this table. The first is called 'node_changed' and indexes the 'changed' field, the second is called 'node_created' and indexes the 'created' field. The keys are arbitrary and should be unique within the table - I have never been able to determine whether they need to be unique across the entire schema but better safe than sorry, there's no reason not to prefix your keys with your table name.

Each index is an array because a single index can track multiple fields (eg 'node_changed_and_created' => array('changed', 'created'),). This is done when you frequently perform queries using both fields together as conditions.

If you need more information I'd recommend the Module Developer support forums for a quicker reply

NancyDru’s picture

Some times, you just can't afford to uninstall the module. So use a hook_update_N() to add the table:

function connect_blocks_schema() {
  $schema['connect_email_queue'] = connect_blocks_queue_table();

  return $schema;

function connect_blocks_queue_table() {
  return array(
    'description' => 'Connect Queue for Delayed Email',
    'fields' => array(
      'id' => array(
        'description' => 'The row identifier.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
    'primary key' => array('id'),
    'indexes' => array(
      'uid' => array('uid'),
      'nid' => array('nid'),
      'queue' => array('uid', 'nid', 'type'),

 * Add Connect_email_queue table.
function connect_blocks_update_7000() {
  if (!db_table_exists('connect_email_queue')) {
    db_create_table('connect_email_queue', connect_blocks_queue_table());