MySQL Reference Manual for version 4.1.0-alpha.


6.5 数据定义: CREATEDROPALTER

6.5.1 CREATE DATABASE 句法

CREATE DATABASE [IF NOT EXISTS] db_name

CREATE DATABASE 以给定名字创建一个数据库。允许的数据库名规则在章节 6.1.2 数据库、表、索引、列和别名 中被给出。 如果数据库已经存在,并且你没有指定 IF NOT EXISTS,这时会产生一个错误。

在 MySQL 中,数据库以包含数据库表对应文件的目录实现的。因为数据库在初始创建时没有表,所以 CREATE DATABASE 语句只在 MySQL 数据目录下创建一个目录。

你也可以使用 mysqladmin 创建一个数据库。查看章节 4.8 MySQL 客户端脚本和实用程序

6.5.2 DROP DATABASE 句法

DROP DATABASE [IF EXISTS] db_name

DROP DATABASE 移除数据库是的所有表并删除数据库。如果你在一个符号链接(symbolic link)数据库上执行一个 DROP DATABASE,链接与原始数据库均会被删除。要非常小心地使用这个命令!

DROP DATABASE 返回从数据库目录下删除的文件数目。通常,它是表的数目的三倍,因为第张表通常对应于一个 “.MYD” 文件、一个 “.MYI” 文件和一个 “.frm” 文件。

DROP DATABASE 命令从给定的数据库目录下移除以下列为扩展名的所有文件:

扩展名 扩展名 扩展名 Ext
.BAK .DAT .HSH .ISD
.ISM .ISM .MRG .MYD
.MYI .db .frm

所有包含两个数字的子目录(RAID 目录)也同样被删除。

在 MySQL 3.22 或以后的版本中,你可以使用关键词 IF EXISTS 以防止如果数据库不存在时发生错误。

你也可以使用 mysqladmin 移除数据库。查看章节 4.8 MySQL 客户端脚本和实用程序

6.5.3 CREATE TABLE 句法

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

create_definition:
  col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
            [PRIMARY KEY] [reference_definition]
  or    PRIMARY KEY (index_col_name,...)
  or    KEY [index_name] (index_col_name,...)
  or    INDEX [index_name] (index_col_name,...)
  or    UNIQUE [INDEX] [index_name] (index_col_name,...)
  or    FULLTEXT [INDEX] [index_name] (index_col_name,...)
  or    [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
            [reference_definition]
  or    CHECK (expr)

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

index_col_name:
        col_name [(length)]

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

reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

table_options:
	TYPE = {BDB | HEAP | ISAM | InnoDB | MERGE | MRG_MYISAM | MYISAM }
or	AUTO_INCREMENT = #
or	AVG_ROW_LENGTH = #
or	CHECKSUM = {0 | 1}
or	COMMENT = "string"
or	MAX_ROWS = #
or	MIN_ROWS = #
or	PACK_KEYS = {0 | 1 | DEFAULT}
or	PASSWORD = "string"
or	DELAY_KEY_WRITE = {0 | 1}
or      ROW_FORMAT= { default | dynamic | fixed | compressed }
or	RAID_TYPE= {1 | STRIPED | RAID0 } RAID_CHUNKS=#  RAID_CHUNKSIZE=#
or	UNION = (table_name,[table_name...])
or	INSERT_METHOD= {NO | FIRST | LAST }
or      DATA DIRECTORY="absolute path to directory"
or      INDEX DIRECTORY="absolute path to directory"

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

CREATE TABLE 以给定的名字在当前数据库创建一个表。允许的表名规则在章节 6.1.2 数据库、表、索引、列和别名 中被给出。如果没有当前数据库或表已经存在,一个错误将会发生。

在 MySQL 3.22 或以后的版本中,表名可以被指定为 db_name.tbl_name。不管有没有当前数据库,它也能正常工作。

从 MySQL 3.23 开始,在创建一个表时,你可以使用关键词 TEMPORARY。它的名字被限止在当前连接中,当连接关闭时,临时表会自动地被删除。这就意味着,两个不同的连接可以使用同一个临时表名而不会与另一个冲突,也不会与同名现有的表相冲突(现有表将被隐藏,只到临时表被删除)。从 MySQL 4.0.2 开始,为了能创建临时表,你必须有 CREATE TEMPORARY TABLES 权限。

在 MySQL 3.23 或以后的版本中,你可以使用关键词 IF NOT EXISTS,因而如果表已存在,错误也不会发生。注意,它并不验证表结构是否一致。

在 MySQL 4.1 中你可以使用 LIKE 来基于一个表定义创建另一个表。to create a table based on a table definition in another table. In MySQL 4.1 中,你同样也可以为一个被生成的列指定类型:

CREATE TABLE foo (a tinyint not null) SELECT b+1 AS 'a' FROM bar;

第张表 tbl_name 由数据库目录下的一些文件表示。对于 MyISAM 类型的表,你将得到:

文件 用途
tbl_name.frm 表定义 (form) 文件
tbl_name.MYD 数据文件
tbl_name.MYI 索引文件

对于各种列类型的性质的更多信息,查看章节 6.2 列类型

6.5.3.1 隐式的列定义变化

在某些情况下,MySQL 隐式地改变一个在 CREATE TABLE 给定的列的规约。(这在 ALTER TABLE 中也可能发生。):

如果你希望知道在你创建或改变了你的表后, MySQL 是否使用了不同于你所指定的列类型,你可以发出一个 DESCRIBE tbl_name 语句。

如果你使用 myisampack 压缩一个表,其它的某些列类型可能会发生改变。查看章节 7.1.2.3 压缩表的特征

6.5.4 ALTER TABLE 句法

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

alter_specification:
        ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
  or    ADD [COLUMN] (create_definition, create_definition,...)
  or    ADD INDEX [index_name] (index_col_name,...)
  or    ADD PRIMARY KEY (index_col_name,...)
  or    ADD UNIQUE [index_name] (index_col_name,...)
  or    ADD FULLTEXT [index_name] (index_col_name,...)
  or	ADD [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
            [reference_definition]
  or    ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  or    CHANGE [COLUMN] old_col_name create_definition
               [FIRST | AFTER column_name]
  or    MODIFY [COLUMN] create_definition [FIRST | AFTER column_name]
  or    DROP [COLUMN] col_name
  or    DROP PRIMARY KEY
  or    DROP INDEX index_name
  or    DISABLE KEYS
  or    ENABLE KEYS
  or    RENAME [TO] new_tbl_name
  or    ORDER BY col
  or    table_options

ALTER TABLE 允许你改变一个现有表的结构。例如,你可以添加或删除列,创建或撤销索引,更改现有列的类型或将列或表自身更名。你也可以改变表的注释和表的类型。查看章节 6.5.3 CREATE TABLE 句法

如果你使用 ALTER TABLE 来改变一个列规约,但是 DESCRIBE tbl_name 显示你的列并没有被修改,这有可能是因为章节 6.5.3.1 隐式的列定义变化 描述的一个原因,使 MySQL 忽略了你的修改。例如,如果你尝试将一个 VARCHAR 列更改为 CHAR,而如果在这个表中包含其它的变长列,MySQL 将仍然使用 VARCHAR

ALTER TABLE 通过建立原初表的一个临时副本来工作。更改在副本上执行,然后原初表将被删除,临时表被换名。这样做使所有的修改自动地转向到没有任何更新失败的新表。当 ALTER TABLE 执行时,原初表可被其它客户端读取。更新与写入被延迟到新的表准备好。

注意,如果你以除 RENAME 之外的其它选项使用 ALTER TABLE ,MySQL 将总是创建一个临时表,即使数据并不确实需要被复制(就像当你改变一个列名时)。我们计划不久来修正它,但是通常人们是不经常执行 ALTER TABLE的,所以在我们的 TODO 上,这个修正并不是急于处理的。对于 MyISAM 表,你可以将变量 myisam_sort_buffer_size 设置和高一点,以加速索引的重建部分(这是重建进程中最慢的部分)。

这里是一个例子,显示了 ALTER TABLE 的一些用法。我们以一个按如下方式创建一个表 t1 开始:

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

为了将表 t1 重命名为 t2

mysql> ALTER TABLE t1 RENAME t2;

为了将列 aINTEGER 改变为 TINYINT NOT NULL(列名不变),并将列 bCHAR(10) 改变为 CHAR(20) ,同时也将 b 重命名为 c

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

添加一个名为 dTIMESTAMP c列:

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

在列 d 上增加一个索引,将列 a 设为主键:

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

移除列 c:

mysql> ALTER TABLE t2 DROP COLUMN c;

添加一个名为 cAUTO_INCREMENT 整型列:

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

注意,我们索引了 c,因为 AUTO_INCREMENT 列必须被索引,同样我们声明列 cNOT NULL,因为被索引的列不能有 NULL

当你添加一个 AUTO_INCREMENT 列时,列值会自动地以序列值填充。通过在 ALTER TABLE 或使用 AUTO_INCREMENT = # 表选项之前执行 SET INSERT_ID=# ,你可以设置第一个序列数字。查看章节 5.5.6 SET 句法

对于 MyISAM 表,如果你不改变 AUTO_INCREMENT 列,序列值将不会被影响。如果你移除一个AUTO_INCREMENT 列,并添加另一个 AUTO_INCREMENT 列,值将再次从 1 开始。

查看章节 A.6.1 ALTER TABLE 的问题

6.5.5 RENAME TABLE 句法

RENAME TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2,...]

更名是以原子方式(atomically)执行,这就意味着,当更名正在运行时,其它的任何线程均不能该表。这使得以一个空表替换一个表成为可能。

CREATE TABLE new_table (...);
RENAME TABLE old_table TO backup_table, new_table TO old_table;

改名是从左到右执行的,这就意味着,如果你希望交换两个表名,你不得不这样做:

RENAME TABLE old_table    TO backup_table,
             new_table    TO old_table,
             backup_table TO new_table;

只要两个数据库在同一个磁盘上,你也可以从一个数据库更名到另一个数据库:

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

当你执行 RENAME 时,你不能有任何锁定的表或活动的事务。你同样也必须有对原初表的 ALTERDROP 权限,以及对新表的 CREATEINSERT 权限。

如果在多表更名中,MySQL 遭遇到任何错误,它将对所有被更名的表进行倒退更名,将每件事物退回到最初状态。

RENAME TABLE 在 MySQL 3.23.23 中被加入。

6.5.6 DROP TABLE 句法

DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name,...] [RESTRICT | CASCADE]

DROP TABLE 移除一个或多个表。所有的数据和表定义均被 移除,所以,一定要小心地使用这个命令!

在 MySQL 3.22 或更新的版本中,你可以使用关键词 IF EXISTS 防止表不存在时发生错误。在 4.1 中,当使用 IF EXISTS 时,对于所有不存在的表,你将得到一个 NOTE。查看章节 4.5.6.9 SHOW WARNINGS | ERRORS

RESTRICT and CASCADE 被允许是为了更容易的移植。目前,他们不起任何作用。

注意:DROP TABLE 将自动地提交当前活动的事务(除非你使用的是MySQL 4.1 ,并且使用了 TEMPORARY 关键词)。

选项 TEMPORARY 在 4.0 中被忽略。在 4.1 中,这人选项按如下所示工作:

使用 TEMPORARY 是一个很好的安全方式,它可以防止你意外地移除一个真实的表。

6.5.7 CREATE INDEX 句法

CREATE [UNIQUE|FULLTEXT] INDEX index_name
       ON tbl_name (col_name[(length)],... )

CREATE INDEX 句法在 MySQL 3.22 以前的版本中不做任何事情。在 3.22 或以后的版本中,CREATE INDEX 被映射到一个 ALTER TABLE 语句来创建索引。查看章节 6.5.4 ALTER TABLE 句法

通常,在用 CREATE TABLE 创建表本身时你就创建表的所有索引。查看章节 6.5.3 CREATE TABLE 句法CREATE INDEX 允许你在一个现有表上添加索引。

(col1,col2,...) 格式的列列表创建一个多列索引。索引值由给定的列值连接而成。

对于 CHARVARCHAR 列,使用 col_name(length) 句法,可以只用一个列的部分来创建索引。(对于 BLOBTEXT 列,长度是必须的。)这里的语句显示使用 name 列的前 10 个字符创建一个索引:

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

因为,大多数名字通常在前 10 个字符是不一样的,这个索引不应该比以整个 name 创建的索引慢。同样,使用部分列值创建的索引文件会更小一点,这将节省很多磁盘空间,也可以加速 INSERT 操作!

注意,如果你存在使用的是 MySQL 3.23.2 或更新的版本并且是 MyISAM 表类型,这时你才能在一个可以有 NULL 值的列上创建索引,以及在一个 BLOB/TEXT列上创建索引。

关于 MySQL 如何使用索引的更多信息,查看章节 5.4.3 MySQL 如何使用索引

FULLTEXT 索引只能索引 VARCHARTEXT 列,而且只能应用于 MyISAM 表。FULLTEXT 索引在 MySQL 3.23.23 和更新的版本中可以使用。查看章节 6.8 MySQL 全文搜索

6.5.8 DROP INDEX 句法

DROP INDEX index_name ON tbl_name

DROP INDEX 从表 tbl_name 移除一个名为 index_name 的索引。在 MySQL 3.22 先前的版本中不做任何事情。在 3.22 或以后的版本中,DROP INDEX 被映射到一个 ALTER TABLE 语句来移除索引。查看章节 6.5.4 ALTER TABLE 句法