Chapter 13. SQL Statement Syntax

Table of Contents

13.1. Data Definition Statements
13.1.1. ALTER DATABASE Syntax
13.1.2. ALTER TABLE Syntax
13.1.3. CREATE DATABASE Syntax
13.1.4. CREATE INDEX Syntax
13.1.5. CREATE TABLE Syntax
13.1.6. DROP DATABASE Syntax
13.1.7. DROP INDEX Syntax
13.1.8. DROP TABLE Syntax
13.1.9. RENAME TABLE Syntax
13.2. Data Manipulation Statements
13.2.1. DELETE Syntax
13.2.2. DO Syntax
13.2.3. HANDLER Syntax
13.2.4. INSERT Syntax
13.2.5. LOAD DATA INFILE Syntax
13.2.6. REPLACE Syntax
13.2.7. SELECT Syntax
13.2.8. Subquery Syntax
13.2.9. TRUNCATE Syntax
13.2.10. UPDATE Syntax
13.3. MySQL Utility Statements
13.3.1. DESCRIBE Syntax (Get Information About Columns)
13.3.2. USE Syntax
13.4. MySQL Transactional and Locking Statements
13.4.1. START TRANSACTION, COMMIT, and ROLLBACK Syntax
13.4.2. Statements That Cannot Be Rolled Back
13.4.3. Statements That Cause an Implicit Commit
13.4.4. SAVEPOINT and ROLLBACK TO SAVEPOINT Syntax
13.4.5. LOCK TABLES and UNLOCK TABLES Syntax
13.4.6. SET TRANSACTION Syntax
13.4.7. XA Transactions
13.5. Database Administration Statements
13.5.1. Account Management Statements
13.5.2. Table Maintenance Statements
13.5.3. SET Syntax
13.5.4. SHOW Syntax
13.5.5. Other Administrative Statements
13.6. Replication Statements
13.6.1. SQL Statements for Controlling Master Servers
13.6.2. SQL Statements for Controlling Slave Servers
13.7. SQL Syntax for Prepared Statements

This chapter describes the syntax for SQL statements.

13.1. Data Definition Statements

13.1.1. ALTER DATABASE Syntax

ALTER {DATABASE | SCHEMA} [db_name]
    alter_specification [, alter_specification] ...

alter_specification:
    [DEFAULT] CHARACTER SET charset_name
  | [DEFAULT] COLLATE collation_name

ALTER DATABASE allows you to change the overall characteristics of a database. These characteristics are stored in the db.opt file in the database directory. To use ALTER DATABASE, you need the ALTER privilege on the database.

The CHARACTER SET clause changes the default database character set. The COLLATE clause changes the default database collation. Character set and collation names are discussed in Chapter 10, Character Set Support.

The database name can be omitted, in which case, the statement applies to the default database. ALTER SCHEMA can be also used.

13.1.2. ALTER TABLE Syntax

ALTER [IGNORE] TABLE tbl_name
    alter_specification [, alter_specification] ...

alter_specification:
    ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
  | ADD [COLUMN] (column_definition,...)
  | ADD INDEX [index_name] [index_type] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        PRIMARY KEY [index_type] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        UNIQUE [index_name] [index_type] (index_col_name,...)
  | ADD [FULLTEXT|SPATIAL] [index_name] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        FOREIGN KEY [index_name] (index_col_name,...)
        [reference_definition]
  | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  | CHANGE [COLUMN] old_col_name column_definition
        [FIRST|AFTER col_name]
  | MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]
  | DROP [COLUMN] col_name
  | DROP PRIMARY KEY
  | DROP INDEX index_name
  | DROP FOREIGN KEY fk_symbol
  | DISABLE KEYS
  | ENABLE KEYS
  | RENAME [TO] new_tbl_name
  | ORDER BY col_name
  | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
  | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
  | DISCARD TABLESPACE
  | IMPORT TABLESPACE
  | table_options
  | partition_options
  | ADD PARTITION partition_definition
  | DROP PARTITION partition_names
  | COALESCE PARTITION number
  | REORGANIZE PARTITION partition_names INTO (partition_definitions)
  | ANALYZE PARTITION partition_names
  | CHECK PARTITION partition_names
  | OPTIMIZE PARTITION partition_names
  | REBUILD PARTITION partition_names
  | REPAIR PARTITION partition_names

ALTER TABLE allows you to change the structure of an existing table. For example, you can add or delete columns, create or destroy indexes, change the type of existing columns, or rename columns or the table itself. You can also change the comment for the table and type of the table.

The syntax for many of the allowable alterations is similar to clauses of the CREATE TABLE statement. This includes table_options modifications, for options such as ENGINE, AUTO_INCREMENT, and AVG_ROW_LENGTH. See Section 13.1.5, “CREATE TABLE Syntax”.

Some operations may result in warnings if attempted on a table for which the storage engine does not support the operation. These warnings can be displayed with SHOW WARNINGS. See Section 13.5.4.22, “SHOW WARNINGS Syntax”.

If you use ALTER TABLE to change a column specification but DESCRIBE tbl_name indicates that your column was not changed, it is possible that MySQL ignored your modification for one of the reasons described in Section 13.1.5.1, “Silent Column Specification Changes”. For example, if you try to change a VARCHAR column to CHAR, MySQL still uses VARCHAR if the table contains other variable-length columns.

ALTER TABLE works by making a temporary copy of the original table. The alteration is performed on the copy, then the original table is deleted and the new one is renamed. While ALTER TABLE is executing, the original table is readable by other clients. Updates and writes to the table are stalled until the new table is ready, then are automatically redirected to the new table without any failed updates.

Note that if you use any other option to ALTER TABLE than RENAME, MySQL always creates a temporary table, even if the data wouldn't strictly need to be copied (such as when you change the name of a column). For MyISAM tables, you can speed up the index re-creation operation (which is the slowest part of the alteration process) by setting the myisam_sort_buffer_size system variable to a high value.

  • To use ALTER TABLE, you need ALTER, INSERT, and CREATE privileges for the table.

  • IGNORE is a MySQL extension to standard SQL. It controls how ALTER TABLE works if there are duplicates on unique keys in the new table or if warnings occur when STRICT mode is enabled. If IGNORE is not specified, the copy is aborted and rolled back if duplicate-key errors occur. If IGNORE is specified, then for rows with duplicates on a unique key, only the first row is used. The others conflicting rows are deleted. Wrong values are truncated to the closest matching acceptable value.

  • You can issue multiple ADD, ALTER, DROP, and CHANGE clauses in a single ALTER TABLE statement, separated by commas. This is a MySQL extension to standard SQL, which allows only one of each clause per ALTER TABLE statement. For example, to drop multiple columns in a single statement:

    mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
    
  • CHANGE col_name, DROP col_name, and DROP INDEX are MySQL extensions to standard SQL.

  • MODIFY is an Oracle extension to ALTER TABLE.

  • The word COLUMN is purely optional and can be omitted.

  • If you use ALTER TABLE tbl_name RENAME TO new_tbl_name without any other options, MySQL simply renames any files that correspond to the table tbl_name. There is no need to create a temporary table. (You can also use the RENAME TABLE statement to rename tables. See Section 13.1.9, “RENAME TABLE Syntax”.)

  • column_definition clauses use the same syntax for ADD and CHANGE as for CREATE TABLE. Note that this syntax includes the column name, not just the column type. See Section 13.1.5, “CREATE TABLE Syntax”.

  • You can rename a column using a CHANGE old_col_name column_definition clause. To do so, specify the old and new column names and the type that the column currently has. For example, to rename an INTEGER column from a to b, you can do this:

    mysql> ALTER TABLE t1 CHANGE a b INTEGER;
    

    If you want to change a column's type but not the name, CHANGE syntax still requires an old and new column name, even if they are the same. For example:

    mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
    

    You can also use MODIFY to change a column's type without renaming it:

    mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
    
  • If you use CHANGE or MODIFY to shorten a column for which an index exists on the column, and the resulting column length is less than the index length, MySQL shortens the index automatically.

  • When you change a column type using CHANGE or MODIFY, MySQL tries to convert existing column values to the new type as well as possible.

  • You can use FIRST or AFTER col_name to add a column at a specific position within a table row. The default is to add the column last. You can also use FIRST and AFTER in CHANGE or MODIFY operations.

  • ALTER COLUMN specifies a new default value for a column or removes the old default value. If the old default is removed and the column can be NULL, the new default is NULL. If the column cannot be NULL, MySQL assigns a default value, as described in Section 13.1.5, “CREATE TABLE Syntax”.

  • DROP INDEX removes an index. This is a MySQL extension to standard SQL. See Section 13.1.7, “DROP INDEX Syntax”.

  • If columns are dropped from a table, the columns are also removed from any index of which they are a part. If all columns that make up an index are dropped, the index is dropped as well.

  • If a table contains only one column, the column cannot be dropped. If what you intend is to remove the table, use DROP TABLE instead.

  • DROP PRIMARY KEY drops the primary index. Note: In older versions of MySQL, if no primary index existed, then DROP PRIMARY KEY would drop the first UNIQUE index in the table. This is not the case in MySQL 5.1, where trying to use DROP PRIMARY KEY on a table with no primary key will give rise to an error.

    If you add a UNIQUE INDEX or PRIMARY KEY to a table, it is stored before any non-unique index so that MySQL can detect duplicate keys as early as possible.

  • ORDER BY allows you to create the new table with the rows in a specific order. Note that the table does not remain in this order after inserts and deletes. This option is mainly useful when you know that you are mostly going to query the rows in a certain order; by using this option after big changes to the table, you might be able to get higher performance. In some cases, it might make sorting easier for MySQL if the table is in order by the column that you want to order it by later.

  • If you use ALTER TABLE on a MyISAM table, all non-unique indexes are created in a separate batch (as for REPAIR TABLE). This should make ALTER TABLE much faster when you have many indexes.

    This feature can be activated explicitly. ALTER TABLE ... DISABLE KEYS tells MySQL to stop updating non-unique indexes for a MyISAM table. ALTER TABLE ... ENABLE KEYS then should be used to re-create missing indexes. MySQL does this with a special algorithm that is much faster than inserting keys one by one, so disabling keys before performing bulk insert operations should give a considerable speedup. Using ALTER TABLE ... DISABLE KEYS requires the INDEX privilege in addition to the privileges mentioned earlier.

  • The FOREIGN KEY and REFERENCES clauses are supported by the InnoDB storage engine, which implements ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...). See Section 15.2.6.4, “FOREIGN KEY Constraints”. For other storage engines, the clauses are parsed but ignored. The CHECK clause is parsed but ignored by all storage engines. See Section 13.1.5, “CREATE TABLE Syntax”. The reason for accepting but ignoring syntax clauses is for compatibility, to make it easier to port code from other SQL servers, and to run applications that create tables with references. See Section 1.8.5, “MySQL Differences from Standard SQL”.

  • InnoDB supports the use of ALTER TABLE to drop foreign keys:

    ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;
    

    For more information, see Section 15.2.6.4, “FOREIGN KEY Constraints”.

  • ALTER TABLE ignores the DATA DIRECTORY and INDEX DIRECTORY table options.

  • If you want to change the table default character set and all character columns (CHAR, VARCHAR, TEXT) to a new character set, use a statement like this:

    ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;
    

    Warning: The preceding operation converts column values between the character sets. This is not what you want if you have a column in one character set (like latin1) but the stored values actually use some other, incompatible character set (like utf8). In this case, you have to do the following for each such column:

    ALTER TABLE t1 CHANGE c1 c1 BLOB;
    ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
    

    The reason this works is that there is no conversion when you convert to or from BLOB columns.

    If you specify CONVERT TO CHARACTER SET binary, the CHAR, VARCHAR, and TEXT columns are converted to their corresponding binary string types (BINARY, VARBINARY, BLOB). This means that the columns no longer will have a character set and a subsequent CONVERT TO operation will not apply to them.

    To change only the default character set for a table, use this statement:

    ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;
    

    The word DEFAULT is optional. The default character set is the character set that is used if you do not specify the character set for a new column which you add to a table (for example, with ALTER TABLE ... ADD column).

    Warning: ALTER TABLE ... DEFAULT CHARACTER SET and ALTER TABLE ... CHARACTER SET are equivalent and change only the default table character set.

  • For an InnoDB table that is created with its own tablespace in an .ibd file, that file can be discarded and imported. To discard the .ibd file, use this statement:

    ALTER TABLE tbl_name DISCARD TABLESPACE;
    

    This deletes the current .ibd file, so be sure that you have a backup first. Attempting to access the table while the tablespace file is discarded results in an error.

    To import the backup .ibd file back into the table, copy it into the database directory, then issue this statement:

    ALTER TABLE tbl_name IMPORT TABLESPACE;
    

    See Section 15.2.6.6, “Using Per-Table Tablespaces”.

  • With the mysql_info() C API function, you can find out how many records were copied, and (when IGNORE is used) how many records were deleted due to duplication of unique key values. See Section 25.2.3.34, “mysql_info().

  • ALTER TABLE can also be used with partitioned tables for repartitioning, for adding, dropping, merging, and splitting partitions, and for performing partitioning maintenance.

    Simply using a partition_options clause with ALTER TABLE on a partitioned table repartitions the table according to the partitioning scheme defined by the partition_options. This clause always begins with PARTITION BY, and follows the same syntax and other rules as apply to the partition_options clause for CREATE TABLE (see Section 13.1.5, “CREATE TABLE Syntax” for more detailed information). Note: This syntax currently is accepted by the MySQL 5.1 server, but does not yet actually do anything; we expect to implement this as MySQL 5.1 is developed.

    The partition_definition clause for ALTER TABLE ADD PARTITION supports the same options as the clause of the same name does for the CREATE TABLE statement clause of the same name. (See Section 13.1.5, “CREATE TABLE Syntax” for the syntax and description.) For example, suppose you have the partitioned table created as shown here:

    CREATE TABLE t1 (
        id INT,
        year_col INT
    )
    PARTITION BY RANGE (year_col) (
        PARTITION p0 VALUES LESS THAN (1991),
        PARTITION p1 VALUES LESS THAN (1995),
        PARTITION p2 VALUES LESS THAN (1999)
    );    
    

    You can add a new partition p3 to this table for storing values less then 2002 as follows:

    ALTER TABLE t1 ADD PARTITION p3 VALUES LESS THAN (2002);
    

    Note: You cannot use ALTER TABLE to add partitions to a table that is not not already partitioned.

    DROP PARTITION can be used to drop one or more RANGE or LIST partitions. This command cannot be used with HASH or KEY partitions; instead, use COALESCE PARTITION (see below). Any data that was stored in the dropped partitions named in the partition_names list is discarded. For example, given the table t1 defined previously, you can drop the partitions named p0 and p1 as shown here:

    ALTER TABLE DROP PARTITION p0, p1;
    

    ADD PARTITION and DROP PARTITION do not currently support IF [NOT] EXISTS. It is also not possible to rename a partition or a partitioned table. Instead, if you wish to rename a partition, you must drop and re-create the partition; if you wish to rename a partitioned table, you must instead drop all partitions, rename the table, then add back the partitions that were dropped.

    COALESCE PARTITION can be used with a table that is partitioned by HASH or KEY to reduce the number of partitions by number. For example, suppose that you have created table t2 using the following:

    CREATE TABLE t2 (
        name VARCHAR (30),
        started DATE
    )
    PARTITION BY HASH(YEAR(started))
    PARTITIONS (6);
    

    You can reduce the number of partitions used by t2 from 6 to 4 using the following command:

    ALTER TABLE t2 COALESCE PARTITION 2;
    

    The data contained in the last number partitions will be merged into the remaining partitions. In this case, partitions 4 and 5 will be merged into the first 4 partitions (the partitions numbered 0, 1, 2, and 3).

    To change some but not all the partitions used by a partitioned table, you can use REORGANIZE PARTITION. This command can be used in several ways:

    • To merge a set of partitions into a single partition. This can be done by naming several partitions in the partition_names list and supplying a single definition for partition_definition.

    • To split an existing partition into several partitions. You can accomplish this by naming a single partition for partition_names and providing multiple partition_definitions.

    • To change the ranges for a subset of partitions defined using VALUES LESS THAN or the value lists for a subset of partitions defined using VALUES IN.

    Note: For partitions that have not been explicitly named, MySQL automatically provides the default names p0, p1, p2, and so on.

    For more detailed information about and examples of ALTER TABLE ... REORGANIZE PARTITION commands, see Section 18.3, “Partition Management”.

  • Several additional clauses provide partition maintenance and repair functionality analogous to that implemented for non-partitioned tables by commands such as CHECK TABLE and REPAIR TABLE (which are not supported for partitioned tables). These include ANALYZE PARTITION, CHECK PARTITION, OPTIMIZE PARTITION, REBUILD PARTITION, and REPAIR PARTITION. Each of these options takes a partition_names clause consisting of one or more names of partitions. The partitions must already exist in the table to be altered. Multiple partition names are separated by commas. For more information, and for examples of these, see Section 18.3.3, “Maintenance of Partitions”.

Here are some examples that show uses of ALTER TABLE. Begin with a table t1 that is created as shown here:

mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

To rename the table from t1 to t2:

mysql> ALTER TABLE t1 RENAME t2;

To change column a from INTEGER to TINYINT NOT NULL (leaving the name the same), and to change column b from CHAR(10) to CHAR(20) as well as renaming it from b to c:

mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

To add a new TIMESTAMP column named d:

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

To add indexes on column d and on column a:

mysql> ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);

To remove column c:

mysql> ALTER TABLE t2 DROP COLUMN c;

To add a new AUTO_INCREMENT integer column named c:

mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
    ->     ADD PRIMARY KEY (c);

Note that we indexed c (as a PRIMARY KEY), because AUTO_INCREMENT columns must be indexed, and also that we declare c as NOT NULL, because primary key columns cannot be NULL.

When you add an AUTO_INCREMENT column, column values are filled in with sequence numbers for you automatically. For MyISAM tables, you can set the first sequence number by executing SET INSERT_ID=value before ALTER TABLE or by using the AUTO_INCREMENT=value table option. See Section 13.5.3, “SET Syntax”.

You can use the ALTER TABLE ... AUTO_INCREMENT=value table option for InnoDB tables to set the sequence number for new rows if the value is greater than the maximum value in the AUTO_INCREMENT column. If the value is less than the current maximum value in the column, no error message is given and the current sequence value is not changed.

With MyISAM tables, if you do not change the AUTO_INCREMENT column, the sequence number is not affected. If you drop an AUTO_INCREMENT column and then add another AUTO_INCREMENT column, the numbers are resequenced beginning with 1.

See Section A.7.1, “Problems with ALTER TABLE.

13.1.3. CREATE DATABASE Syntax

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
    [create_specification [, create_specification] ...]

create_specification:
    [DEFAULT] CHARACTER SET charset_name
  | [DEFAULT] COLLATE collation_name

CREATE DATABASE creates a database with the given name. To use CREATE DATABASE, you need the CREATE privilege on the database.

Rules for allowable database names are given in Section 9.2, “Database, Table, Index, Column, and Alias Names”. An error occurs if the database exists and you did not specify IF NOT EXISTS.

create_specification options specify database characteristics. Database characteristics are stored in the db.opt file in the database directory. The CHARACTER SET clause specifies the default database character set. The COLLATE clause specifies the default database collation. Character set and collation names are discussed in Chapter 10, Character Set Support.

Databases in MySQL are implemented as directories containing files that correspond to tables in the database. Because there are no tables in a database when it is initially created, the CREATE DATABASE statement creates only a directory under the MySQL data directory and the db.opt file.

If you manually create a directory under the data directory (for example, with mkdir), the server considers it a database directory and it shows up in the output of SHOW DATABASES.

CREATE SCHEMA can also be used.

You can also use the mysqladmin program to create databases. See Section 8.5, “mysqladmin — Client for Administering a MySQL Server”.

13.1.4. CREATE INDEX Syntax

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [USING index_type]
    ON tbl_name (index_col_name,...)

index_col_name:
    col_name [(length)] [ASC | DESC]

CREATE INDEX is mapped to an ALTER TABLE statement to create indexes. See Section 13.1.2, “ALTER TABLE Syntax”.

Normally, you create all indexes on a table at the time the table itself is created with CREATE TABLE. See Section 13.1.5, “CREATE TABLE Syntax”. CREATE INDEX allows you to add indexes to existing tables.

A column list of the form (col1,col2,...) creates a multiple-column index. Index values are formed by concatenating the values of the given columns.

For CHAR and VARCHAR columns, indexes can be created that use only part of a column, using col_name(length) syntax to index a prefix consisting of the first length characters of each column value. BLOB and TEXT columns also can be indexed, but a prefix length must be given.

The statement shown here creates an index using the first 10 characters of the name column:

CREATE INDEX part_of_name ON customer (name(10));

Because most names usually differ in the first 10 characters, this index should not be much slower than an index created from the entire name column. Also, using partial columns for indexes can make the index file much smaller, which could save a lot of disk space and might also speed up INSERT operations.

Prefixes can be up to 255 bytes long. For MyISAM and InnoDB tables, they may be up to 1000 bytes in length. Note that prefix limits are measured in bytes, whereas the prefix length in CREATE INDEX statements is interpreted as number of characters. Take this into account when specifying a prefix length for a column that uses a multi-byte character set.

In MySQL 5.1:

  • You can add an index on a column that can have NULL values only if you are using the MyISAM, InnoDB, or BDB table type.

  • You can add an index on a BLOB or TEXT column only if you are using the MyISAM, BDB, or InnoDB table type.

An index_col_name specification can end with ASC or DESC. These keywords are allowed for future extensions for specifying ascending or descending index value storage. Currently they are parsed but ignored; index values are always stored in ascending order.

Some storage engines allow you to specify an index type when creating an index. The syntax for the index_type specifier is USING type_name. The allowable type_name values supported by different storage engines are shown in the following table. Where multiple index types are listed, the first one is the default when no index_type specifier is given.

Storage EngineAllowable Index Types
MyISAMBTREE
InnoDBBTREE
MEMORY/HEAPHASH, BTREE

Example:

CREATE TABLE lookup (id INT) ENGINE = MEMORY;
CREATE INDEX id_index USING BTREE ON lookup (id);

TYPE type_name can be used as a synonym for USING type_name to specify an index type. However, USING is the preferred form. In addition, the index name that precedes the index type in the index specification syntax is not optional with TYPE. This is because, unlike USING, TYPE is not a reserved word and thus is interpreted as an index name.

If you specify an index type that is not legal for a given storage engine, but there is another index type available that the engine can use without affecting query results, the engine uses the available type.

For more information about how MySQL uses indexes, see Section 7.4.5, “How MySQL Uses Indexes”.

FULLTEXT indexes can index only CHAR, VARCHAR, and TEXT columns, and only in MyISAM tables. See Section 12.7, “Full-Text Search Functions”.

SPATIAL indexes can index only spatial columns, and only in MyISAM tables. Spatial column types are described in Chapter 19, Spatial Extensions in MySQL.

13.1.5. CREATE TABLE Syntax

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(create_definition,...)]
    [table_options] [select_statement]

Or:

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(] LIKE old_tbl_name [)];

create_definition:
    column_definition
  | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
  | KEY [index_name] [index_type] (index_col_name,...)
  | INDEX [index_name] [index_type] (index_col_name,...)
  | [CONSTRAINT [symbol]] UNIQUE [INDEX]
        [index_name] [index_type] (index_col_name,...)
  | [FULLTEXT|SPATIAL] [INDEX] [index_name] (index_col_name,...)
  | [CONSTRAINT [symbol]] FOREIGN KEY
        [index_name] (index_col_name,...) [reference_definition]
  | CHECK (expr)

column_definition:
    col_name type [NOT NULL | NULL] [DEFAULT default_value]
        [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
        [COMMENT 'string'] [reference_definition]

type:
    TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  | INT[(length)] [UNSIGNED] [ZEROFILL]
  | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  | NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  | DATE
  | TIME
  | TIMESTAMP
  | DATETIME
  | CHAR(length) [BINARY | ASCII | UNICODE]
  | VARCHAR(length) [BINARY]
  | TINYBLOB
  | BLOB
  | MEDIUMBLOB
  | LONGBLOB
  | TINYTEXT [BINARY]
  | TEXT [BINARY]
  | MEDIUMTEXT [BINARY]
  | LONGTEXT [BINARY]
  | ENUM(value1,value2,value3,...)
  | SET(value1,value2,value3,...)
  | spatial_type

index_col_name:
    col_name [(length)] [ASC | DESC]

reference_definition:
    REFERENCES tbl_name [(index_col_name,...)]
               [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
               [ON DELETE reference_option]
               [ON UPDATE reference_option]

reference_option:
    RESTRICT | CASCADE | SET NULL | NO ACTION

table_options: table_option [table_option] ...

table_option:
    {ENGINE|TYPE} = engine_name
  | AUTO_INCREMENT = value
  | AVG_ROW_LENGTH = value
  | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
  | CHECKSUM = {0 | 1}
  | COMMENT = 'string'
  | CONNECTION = 'connect_string'
  | MAX_ROWS = value
  | MIN_ROWS = value
  | PACK_KEYS = {0 | 1 | DEFAULT}
  | PASSWORD = 'string'
  | DELAY_KEY_WRITE = {0 | 1}
  | ROW_FORMAT = {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
  | UNION = (tbl_name[,tbl_name]...)
  | INSERT_METHOD = { NO | FIRST | LAST }
  | DATA DIRECTORY = 'absolute path to directory'
  | INDEX DIRECTORY = 'absolute path to directory'

partition_options:
    PARTITION BY
           [LINEAR] HASH(expr)
        |  [LINEAR] KEY(column_list)
        |  RANGE(expr)
        |  LIST(column_list)
    [PARTITIONS num]
    [  SUBPARTITION BY
           [LINEAR] HASH(expr)
         | [LINEAR] KEY(column_list)
      [SUBPARTITIONS(num)]  
    ]
    [(partition_definition), [(partition_definition)], ...]

partition_definition:
    PARTITION partition_name
        [VALUES { 
                  LESS THAN (expr) | MAXVALUE 
                | IN (value_list) }]
        [[STORAGE] ENGINE [=] engine-name]
        [COMMENT [=] 'comment_text' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] (tablespace_name)]
        [NODEGROUP [=] node_group_id]
        [(subpartition_definition), [(subpartition_definition)], ...]

subpartition_definition:
    SUBPARTITION logical_name
        [[STORAGE] ENGINE [=] engine-name]
        [COMMENT [=] 'comment_text' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] (tablespace_name)]
        [NODEGROUP [=] node_group_id]

select_statement:
    [IGNORE | REPLACE] [AS] SELECT ...   (Some legal select statement)

CREATE TABLE creates a table with the given name. You must have the CREATE privilege for the table.

Rules for allowable table names are given in Section 9.2, “Database, Table, Index, Column, and Alias Names”. By default, the table is created in the current database. An error occurs if the table exists, if there is no current database, or if the database does not exist.

The table name can be specified as db_name.tbl_name to create the table in a specific database. This works whether or not there is a current database. If you use quoted identifiers, quote the database and table names separately. For example, `mydb`.`mytbl` is legal, but `mydb.mytbl` is not.

You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only to the current connection, and is dropped automatically when the connection is closed. This means that two different connections can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name. (The existing table is hidden until the temporary table is dropped.) You must have the CREATE TEMPORARY TABLES privilege to be able to create temporary tables.

The keywords IF NOT EXISTS prevent an error from occurring if the table exists. Note that there is no verification that the existing table has a structure identical to that indicated by the CREATE TABLE statement. Note: If you use IF NOT EXISTS in a CREATE TABLE ... SELECT statement, any records selected by the SELECT part are inserted whether or not the table already exists.

MySQL represents each table by an .frm table format (definition) file in the database directory. The storage engine for the table might create other files as well. In the case of MyISAM tables, the storage engine creates data and index files. Thus, for each MyISAM table tbl_name, there are three disk files:

FilePurpose
tbl_name.frmTable format (definition) file
tbl_name.MYDData file
tbl_name.MYIIndex file

The files created by each storage engine to represent tables are described in Chapter 15, Storage Engines and Table Types.

For general information on the properties of the various column types, see Chapter 11, Column Types. For information about spatial column types, see Chapter 19, Spatial Extensions in MySQL.

  • If neither NULL nor NOT NULL is specified, the column is treated as though NULL had been specified.

  • An integer column can have the additional attribute AUTO_INCREMENT. When you insert a value of NULL (recommended) or 0 into an indexed AUTO_INCREMENT column, the column is set to the next sequence value. Typically this is value+1, where value is the largest value for the column currently in the table. AUTO_INCREMENT sequences begin with 1. Such a column must be defined as one of the integer types as described in Section 11.1.1, “Overview of Numeric Types”. (The value 1.0 is not an integer.) See Section 25.2.3.36, “mysql_insert_id().

    Specifying the NO_AUTO_VALUE_ON_ZERO flag for the --sql-mode server option or the sql_mode system variable allows you to store 0 in AUTO_INCREMENT columns as 0 without generating a new sequence value. See Section 5.3.1, “mysqld Command-Line Options”.

    Note: There can be only one AUTO_INCREMENT column per table, it must be indexed, and it cannot have a DEFAULT value. An AUTO_INCREMENT column works properly only if it contains only positive values. Inserting a negative number is regarded as inserting a very large positive number. This is done to avoid precision problems when numbers “wrap” over from positive to negative and also to ensure that you do not accidentally get an AUTO_INCREMENT column that contains 0.

    For MyISAM and BDB tables, you can specify an AUTO_INCREMENT secondary column in a multiple-column key. See Section 3.6.9, “Using AUTO_INCREMENT.

    To make MySQL compatible with some ODBC applications, you can find the AUTO_INCREMENT value for the last inserted row with the following query:

    SELECT * FROM tbl_name WHERE auto_col IS NULL
    
  • Character column definitions can include a CHARACTER SET attribute to specify the character set and, optionally, a collation for the column. For details, see Chapter 10, Character Set Support. CHARSET is a synonym for CHARACTER SET.

    CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);
    

    MySQL 5.1 interprets length specifications in character column definitions in characters. (Some earlier versions interpreted them in bytes.)

  • The DEFAULT clause specifies a default value for a column. With one exception, the default value must be a constant; it cannot be a function or an expression. This means, for example, that you cannot set the default for a date column to be the value of a function such as NOW() or CURRENT_DATE. The exception is that you can specify CURRENT_TIMESTAMP as the default for a TIMESTAMP column. See Section 11.3.1.1, “TIMESTAMP Properties as of MySQL 4.1”.

    BLOB and TEXT columns cannot be assigned a default value.

    If a column definition includes no explicit DEFAULT value, MySQL determines the default value as follows:

    If the column can take NULL as a value, the column is defined with an explicit DEFAULT NULL clause. (This is the same as in earlier versions of MySQL.)

    If the column cannot take NULL as the value, MySQL defines the column with no explicit DEFAULT clause. For data entry, if an INSERT or REPLACE statement includes no value for the column, MySQL handles the column according to the SQL mode in effect at the time:

    • If strict mode is not enabled, MySQL sets the column to the implicit default value for the column data type.

    • If strict mode is enabled, an error occurs for transactional tables and the statement is rolled back. For non-transactional tables, an error occurs, but if this happens for the the second or subsequent row of a multiple-row statement, the preceding rows will have been inserted.

    Suppose that a table t is defined as follows:

    CREATE TABLE t (i INT NOT NULL);
    

    In this case, i has no explicit default, so in strict mode each of the following statements produce an error and no row is inserted. When not using strict mode, only the third statement produces an error; the implicit default is inserted for the first two statements, but the third fails because DEFAULT(i) cannot produce a value:

    INSERT INTO t VALUES();
    INSERT INTO t VALUES(DEFAULT);
    INSERT INTO t VALUES(DEFAULT(i));
    

    See Section 5.3.2, “The Server SQL Mode”.

    For a given table, you can use the SHOW CREATE TABLE statement to see which columns have an explicit DEFAULT clause.

  • A comment for a column can be specified with the COMMENT option. The comment is displayed by the SHOW CREATE TABLE and SHOW FULL COLUMNS statements.

  • The attribute SERIAL can be used as an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.

  • KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY can also be specified as just KEY when given in a column definition. This was implemented for compatibility with other database systems.

  • A UNIQUE index is one in which all values in the index must be distinct. An error occurs if you try to add a new row with a key that matches an existing row. The exception to this is that if a column in the index is allowed to contain NULL values, it can contain multiple NULL values. This exception does not apply to BDB tables, for which an indexed column allows only a single NULL.

  • A PRIMARY KEY is a unique KEY where all key columns must be defined as NOT NULL. If they are not explicitly declared as NOT NULL, MySQL declares them so implicitly (and silently). A table can have only one PRIMARY KEY. If you do not have a PRIMARY KEY and an application asks for the PRIMARY KEY in your tables, MySQL returns the first UNIQUE index that has no NULL columns as the PRIMARY KEY.

  • In the created table, a PRIMARY KEY is placed first, followed by all UNIQUE indexes, and then the non-unique indexes. This helps the MySQL optimizer to prioritize which index to use and also more quickly to detect duplicated UNIQUE keys.

  • A PRIMARY KEY can be a multiple-column index. However, you cannot create a multiple-column index using the PRIMARY KEY key attribute in a column specification. Doing so only marks that single column as primary. You must use a separate PRIMARY KEY(index_col_name, ...) clause.

  • If a PRIMARY KEY or UNIQUE index consists of only one column that has an integer type, you can also refer to the column as _rowid in SELECT statements.

  • In MySQL, the name of a PRIMARY KEY is PRIMARY. For other indexes, if you do not assign a name, the index is assigned the same name as the first indexed column, with an optional suffix (_2, _3, ...) to make it unique. You can see index names for a table using SHOW INDEX FROM tbl_name. See Section 13.5.4.11, “SHOW INDEX Syntax”.

  • Some storage engines allow you to specify an index type when creating an index. The syntax for the index_type specifier is USING type_name.

    Example:

    CREATE TABLE lookup
      (id INT, INDEX USING BTREE (id))
      ENGINE = MEMORY;
    

    For details about USING, see Section 13.1.4, “CREATE INDEX Syntax”.

    For more information about how MySQL uses indexes, see Section 7.4.5, “How MySQL Uses Indexes”.

  • In MySQL 5.1, only the MyISAM, InnoDB, BDB, and MEMORY storage engines support indexes on columns that can have NULL values. In other cases, you must declare indexed columns as NOT NULL or an error results.

  • With col_name(length) syntax in an index specification, you can create an index that uses only the first length characters of a CHAR or VARCHAR column. Indexing only a prefix of column values like this can make the index file much smaller. See Section 7.4.3, “Column Indexes”.

    The MyISAM and InnoDB storage engines also support indexing on BLOB and TEXT columns. When indexing a BLOB or TEXT column, you must specify a prefix length for the index. For example:

    CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
    

    Prefixes can be up to 1000 bytes long for MyISAM and InnoDB tables, and 255 bytes for other table types. Note that prefix limits are measured in bytes, whereas the prefix length in CREATE TABLE statements is interpreted as number of characters. Be sure to take this into account when specifying a prefix length for a column that uses a multi-byte character set.

  • An index_col_name specification can end with ASC or DESC. These keywords are allowed for future extensions for specifying ascending or descending index value storage. Currently they are parsed but ignored; index values are always stored in ascending order.

  • When you use ORDER BY or GROUP BY on a TEXT or BLOB column in a SELECT, the server sorts values using only the initial number of bytes indicated by the max_sort_length system variable. See Section 11.4.3, “The BLOB and TEXT Types”.

  • You can create special FULLTEXT indexes, which are used for full-text searches. Only the MyISAM table type supports FULLTEXT indexes. They can be created only from CHAR, VARCHAR, and TEXT columns. Indexing always happens over the entire column; partial indexing is not supported and any prefix length is ignored if specified. See Section 12.7, “Full-Text Search Functions” for details of operation.

  • You can create SPATIAL indexes on spatial column types. Spatial types are supported only for MyISAM tables and indexed columns must be declared as NOT NULL. See Chapter 19, Spatial Extensions in MySQL.

  • InnoDB tables support checking of foreign key constraints. See Section 15.2, “The InnoDB Storage Engine”. Note that the FOREIGN KEY syntax in InnoDB is more restrictive than the syntax presented for the CREATE TABLE statement at the beginning of this section: The columns of the referenced table must always be explicitly named. InnoDB supports both ON DELETE and ON UPDATE actions on foreign keys. For the precise syntax, see Section 15.2.6.4, “FOREIGN KEY Constraints”.

    For other storage engines, MySQL Server parses the FOREIGN KEY and REFERENCES syntax in CREATE TABLE statements, but without further action being taken. The CHECK clause is parsed but ignored by all storage engines. See Section 1.8.5.5, “Foreign Keys”.

  • For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte. The maximum record length in bytes can be calculated as follows:

    row length = 1
                 + (sum of column lengths)
                 + (number of NULL columns + delete_flag + 7)/8
                 + (number of variable-length columns)
    

    delete_flag is 1 for tables with static record format. Static tables use a bit in the row record for a flag that indicates whether the row has been deleted. delete_flag is 0 for dynamic tables because the flag is stored in the dynamic row header.

    These calculations do not apply for InnoDB tables, for which storage size is no different for NULL columns than for NOT NULL columns.

The ENGINE and TYPE options specify the storage engine for the table. ENGINE is the preferred option name.

The ENGINE and TYPE options take the following values:

Storage EngineDescription
ARCHIVEThe archiving storage engine. See Section 15.8, “The ARCHIVE Storage Engine”.
BDBTransaction-safe tables with page locking. Also known as BerkeleyDB. See Section 15.5, “The BDB (BerkeleyDB) Storage Engine”.
CSVTables that store rows in comma-separated values format. See Section 15.9, “The CSV Storage Engine”.
EXAMPLEAn example engine. See Section 15.6, “The EXAMPLE Storage Engine”.
FEDERATEDStorage engine that accesses remote tables. See Section 15.7, “The FEDERATED Storage Engine”.
HEAPSee Section 15.4, “The MEMORY (HEAP) Storage Engine”.
(OBSOLETE) ISAMNot available in MySQL 5.1. If you are upgrading to MySQL 5.1 from a previous version, you should convert any existing ISAM tables to MyISAM before performing the upgrade. See Chapter 15, Storage Engines and Table Types.
InnoDBTransaction-safe tables with row locking and foreign keys. See Section 15.2, “The InnoDB Storage Engine”.
MEMORYThe data for this table type is stored only in memory. (Known in earlier MySQL versions as HEAP.)
MERGEA collection of MyISAM tables used as one table. Also known as MRG_MyISAM. See Section 15.3, “The MERGE Storage Engine”.
MyISAMThe binary portable storage engine that is the default storage engine used by MySQL. See Section 15.1, “The MyISAM Storage Engine”.
NDBCLUSTERClustered, fault-tolerant, memory-based tables. Also known as NDB. See Chapter 17, MySQL Cluster.

For more information about MySQL's storage engines, see Chapter 15, Storage Engines and Table Types.

If a storage engine is specified that is not available, MySQL uses MyISAM instead. For example, if a table definition includes the ENGINE=BDB option but the MySQL server does not support BDB tables, the table is created as a MyISAM table. This makes it possible to have a replication setup where you have transactional tables on the master but tables created on the slave are non-transactional (to get more speed). In MySQL 5.1, a warning occurs if the storage engine specification is not honored.

The other table options are used to optimize the behavior of the table. In most cases, you do not have to specify any of them. These options work for all storage engines unless otherwise indicated:

  • AUTO_INCREMENT

    The initial AUTO_INCREMENT value for the table. In MySQL 5.1, this works for MyISAM and MEMORY tables only. It is also supported for InnoDB. To set the first auto-increment value for engines that do not support the AUTO_INCREMENT table option, insert a “dummy” row with a value one less than the desired value after creating the table, and then delete the dummy row.

    For engines that support the AUTO_INCREMENT table option in CREATE TABLE statements, you can also use ALTER TABLE tbl_name AUTO_INCREMENT = n to reset the AUTO_INCREMENT value.

  • AVG_ROW_LENGTH

    An approximation of the average row length for your table. You need to set this only for large tables with variable-size records.

    When you create a MyISAM table, MySQL uses the product of the MAX_ROWS and AVG_ROW_LENGTH options to decide how big the resulting table is. If you don't specify either option, the maximum size for a table is 65,536TB of data. (If your operating system does not support files that large, table sizes are constrained by the operating system limit.) If you want to keep down the pointer sizes to make the index smaller and faster and you don't really need big files, you can decrease the default pointer size by setting the myisam_data_pointer_size system variable. (See Section 5.3.3, “Server System Variables”.) If you want all your tables to be able to grow above the default limit and are willing to have your tables slightly slower and larger than necessary, you may increase the default pointer size by setting this variable.

  • [DEFAULT] CHARACTER SET

    Specify a default character set for the table. CHARSET is a synonym for this.

    for CHARACTER SET.

  • COLLATE

    Specify a default collation for the table.

  • CHECKSUM

    Set this to 1 if you want MySQL to maintain a live checksum for all rows (that is, a checksum that MySQL updates automatically as the table changes). This makes the table a little slower to update, but also makes it easier to find corrupted tables. The CHECKSUM TABLE statement reports the checksum (MyISAM only).

  • COMMENT

    A comment for the table, up to 60 characters long.

  • CONNECTION

    The connection string for a FEDERATED table. (Note: Older versions of MySQL used a COMMENT option for the connection string.

  • MAX_ROWS

    The maximum number of rows you plan to store in the table. This is not a hard limit, but rather an indicator that the table must be able to store at least this many rows.

  • MIN_ROWS

    The minimum number of rows you plan to store in the table.

  • PACK_KEYS

    Set this option to 1 if you want to have smaller indexes. This usually makes updates slower and reads faster. Setting the option to 0 disables all packing of keys. Setting it to DEFAULT tells the storage engine to pack only long CHAR or VARCHAR columns (MyISAM only).

    If you do not use PACK_KEYS, the default is to pack only strings, but not numbers. If you use PACK_KEYS=1, numbers are packed as well.

    When packing binary number keys, MySQL uses prefix compression:

    • Every key needs one extra byte to indicate how many bytes of the previous key are the same for the next key.

    • The pointer to the row is stored in high-byte-first order directly after the key, to improve compression.

    This means that if you have many equal keys on two consecutive rows, all following “same” keys usually only take two bytes (including the pointer to the row). Compare this to the ordinary case where the following keys takes storage_size_for_key + pointer_size (where the pointer size is usually 4). Conversely, you get a big benefit from prefix compression only if you have many numbers that are the same. If all keys are totally different, you use one byte more per key, if the key is not a key that can have NULL values. (In this case, the packed key length is stored in the same byte that is used to mark if a key is NULL.)

  • PASSWORD

    Encrypt the .frm file with a password. This option does not do anything in the standard MySQL version.

  • DELAY_KEY_WRITE

    Set this to 1 if you want to delay key updates for the table until the table is closed (MyISAM only).

  • ROW_FORMAT

    Defines how the rows should be stored. Currently this option works only with MyISAM tables. The option value can FIXED or DYNAMIC for static or variable-length row format. myisampack sets the type to COMPRESSED. See Section 15.1.3, “MyISAM Table Storage Formats”.

    InnoDB records are stored in compact format (ROW_FORMAT=COMPACT) by default. The non-compact format used in older versions of MySQL can still be requested by specifying ROW_FORMAT=REDUNDANT.

  • RAID_TYPE

    RAID support has been removed as of MySQL 5.0. For information on RAID, see http://dev.mysql.com/doc/refman/4.1/en/create-table.html.

  • UNION

    UNION is used when you want to use a collection of identical tables as one. This works only with MERGE tables. See Section 15.3, “The MERGE Storage Engine”.

    You must have SELECT, UPDATE, and DELETE privileges for the tables you map to a MERGE table. (Note: Formerly, all tables used had to be in the same database as the MERGE table itself. This restriction no longer applies.)

  • INSERT_METHOD

    If you want to insert data into a MERGE table, you must specify with INSERT_METHOD the table into which the row should be inserted. INSERT_METHOD is an option useful for MERGE tables only. Use a value of FIRST or LAST to have inserts go to the first or last table, or a value of NO to prevent inserts. See Section 15.3, “The MERGE Storage Engine”.

  • DATA DIRECTORY, INDEX DIRECTORY

    By using DATA DIRECTORY='directory' or INDEX DIRECTORY='directory' you can specify where the MyISAM storage engine should put a table's data file and index file. Note that the directory should be a full path to the directory (not a relative path).

    These options work only when you are not using the --skip-symbolic-links option. Your operating system must also have a working, thread-safe realpath() call. See Section 7.6.1.2, “Using Symbolic Links for Tables on Unix” for more complete information.

  • partition_options can be used to control partitioning of the table created with CREATE TABLE, and if used, must contain at a minimum a PARTITION BY clause. This clause contains the function which is used to determine the partition; the function returns an integer value ranging from 1 to num, where num is the number of partitions. The choices available for this function which are available in MySQL 5.1 are shown in the following list. Important: Not all options shown in the syntax for partition_options at the beginning of this section are available for all partitioning types. Please see the listings for the individual types below for information specific to each type, and see Chapter 18, Partitioning for more complete information about the workings of and uses for partitioning in MySQL, as well as additional examples of table creation and other commands relating to MySQL partitioning.

    • HASH(expr): Hashes one or more columns to create a key for placing and locating rows. expr is an expression using one or more table columns. This can be any legal MySQL expression (including MySQL functions) that yields a single integer value. For example, these are all valid CREATE TABLE statements using PARTITION BY HASH:

      CREATE TABLE t1 (col1 INT, col2 CHAR(5)) 
          PARTITION BY HASH(col1);
      
      CREATE TABLE t1 (col1 INT, col2 CHAR(5))
          PARTITION BY HASH( ORD(col2) );
      
      CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME)
          PARTITION BY HASH ( YEAR(col3) );
      

      You may not use either VALUES LESS THAN or VALUES IN clauses with PARTITION BY HASH.

      PARTITION BY HASH uses the remainder of expr divided by the number of partitions (that is, the modulus). For examples and additional information, see Section 18.2.3, “HASH Partitioning”.

      The LINEAR keyword entails a somewhat different algorithm. In this case, the number of the partition in which a record is stored is calculated as the result of one or more logical AND operations. For discussion and examples of linear hashing, see Section 18.2.3.1, “LINEAR HASH Partitioning”.

    • KEY(column_list): This is similar to HASH, except that MySQL supplies the hashing function so as to guarantee an even data distribution. The column_list argument is simply a list of table columns. This example shows a simple table partitioned by key, with 4 partitions:

      CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
          PARTITION BY KEY(col3)
          PARTITIONS 4;
      

      You can employ linear partitioning with tables which are partitioned by key, by using the LINEAR keyword. This has the same effect as with tables that are partitioned by HASH; that is, the partition number is found using the & operator rather than the modulus (see Section 18.2.3.1, “LINEAR HASH Partitioning” and Section 18.2.4, “KEY Partitioning” for details). This example uses linear partitioning by key to distribute data between 5 partitions:

      CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
          PARTITION BY LINEAR KEY(col3)
          PARTITIONS 5;
      

      You may not use either VALUES LESS THAN or VALUES IN clauses with PARTITION BY KEY.

    • RANGE: In this case, expr shows a range of values using a set of VALUES LESS THAN operators. When using range partitioning, you must define at least one partition using VALUES LESS THAN. You cannot useVALUES IN with range partitioning.

      VALUES LESS THAN can be used with either a literal value or an expression that evaluates to a single value.

      For example, suppose you have a table that you wish to partition on a column containing year values, according to the following scheme:

      Partition #:Years Range:
      01990 and earlier
      11991 - 1994
      21995 - 1998
      31999 - 2002
      42003 - 2005
      52006 and later

      A table implementing such a partitioning scheme can be realised by the CREATE TABLE statement shown here:

      CREATE TABLE t1 (
          year_col INT, 
          some_data INT 
      ) 
      PARTITION BY RANGE (year_col) (
          PARTITION p0 VALUES LESS THAN (1991),
          PARTITION p1 VALUES LESS THAN (1995),
          PARTITION p2 VALUES LESS THAN (1999),
          PARTITION p3 VALUES LESS THAN (2002),
          PARTITION p4 VALUES LESS THAN (2006),
          PARTITION p5 VALUES LESS THAN MAXVALUE
      );
      

      PARTITION ... VALUES LESS THAN ... statements work in a consecutive fashion. VALUES LESS THAN MAXVALUE works to specify “leftover” values that are greater than the maximum value otherwise specified.

      Note that VALUES LESS THAN clauses work sequentially in a manner similar to that of the case portions of a switch ... case block (as found in many programming languages such as C, Java, and PHP). That is, the clauses must be arranged in such a way that the upper limit specified in each successive VALUES LESS THAN is greater than that of the previous one, with the one referencing MAXVALUE coming last of all in the list.

      VALUES IN is used with a list of values to be matched. For instance, you could create a partitioning scheme such as the following:

      CREATE TABLE client_firms (
          id INT,
          name VARCHAR(35)
      )
      PARTITION BY RANGE (id) (
          PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),
          PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),
          PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
          PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
      );
      

      Currently, the value list used with VALUES IN ... must consist of integer values only.

      (Since this table is partitioned using only VALUES IN expressions, you could instead use PARTITION BY LIST, rather than PARTITION BY RANGE. See next item.)

      In either case — VALUES LESS THAN or VALUES IN — each partition is defined with the syntax PARTITION name, where name is the identifier for the partition, followed by the VALUES ... clause.

    • LIST(expr): This is useful when assigning partitions based on a table column with a restricted set of possible values, such as a state or country code. In such a case, all records pertaining to a certain state or country can be assigned to a single partition, or a partition can be reserved for a certain set of states or countries. It is similar to RANGE, except that only VALUES IN may be used to specify allowable values for each partition.

      When using list partitioning, you must define at least one partition using VALUES IN. You cannot use VALUES LESS THAN with PARTITION BY LIST.

    • The number of partitions may optionally be specified with a PARTITIONS num clause, where num is the number of partitions. If both this clause and any PARTITION clauses are used, then num must be equal to the total number of any partitions that are declared using PARTITION clauses.

      Note: Whether or not you use a PARTITIONS clause in creating a table that is partitioned by RANGE or LIST, you must still include at least one PARTITION VALUES clause in the table definition (see below).

    • A partition may optionally be divided into a number of subpartitions. This can be indicated by using the optional SUBPARTITION BY clause. Subpartitioning may be done by HASH or KEY. Either of these may be LINEAR. These work in the same way as previously described for the equivalent partitioning types. (It is not possible to subpartition by LIST or RANGE.)

      The number of subpartitions can be indicated using the