目录
ALTER {DATABASE | SCHEMA} [db_name]
alter_specification [, alter_specification] ...
alter_specification:
[DEFAULT] CHARACTER SET charset_name
| [DEFAULT] COLLATE collation_name
ALTER DATABASE用于更改数据库的全局特性。这些特性储存在数据库目录中çš�db.opt文件中。要使用ALTER DATABASE,您需要获得数据库ALTER权限ã€�
CHARACTER SET子句用于更改默认的数据库字符集ã€�COLLATE子句用于更改默认的数据库整序。在ç¬�10ç«�ï¼�字符集支æŒ�中对字符集和整序名称进行了讨论ã€�
数据库名称可以忽略,此时,语句对应于默认数据库。也可以使用ALTER SCHEMAã€�
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用于更改原有表的结构。例如,您可以增加或删减列,创建或取消索引,更改原有列的类型,或重新命名列或表。您还可以更改表的评注和表的类型ã€�
允许进行的变更中,许多子句的语法ä¸�CREATE TABLE中的子句的语法相近。其中包æ‹�table_options修改,选项æœ�ENGINE, AUTO_INCREMENTå’�AVG_ROW_LENGTH等。请è§�13.1.5节,“CREATE TABLE语法â€�ã€�
存储引擎不支持有些操作,如果进行这些操作,会出现警告。使ç”�SHOW WARNINGS可以显示出这些警告。请参见13.5.4.22节,“SHOW WARNINGS语法â€�ã€�
如果您使ç”�ALTER TABLE更改列规约,但是DESCRIBE tbl_name提示您列规约并没有改变,则可能是因为MySQL忽略了您所做的更改。忽略更改的原因è§�13.1.5.1节,“沉寂的列规格变更â€�。例如,如果您试图把VARCHAR列更改为CHAR列,此时,如果表包含其它长度可变的列,则MySQL仍会使用VARCHARã€�
ALTER TABLE运行时会对原表进行临时复制,在副本上进行更改,然后删除原表,再对新表进行重命名。在执行ALTER TABLE时,其它用户可以阅读原表,但是对表的更新和修改的操作将被延迟,直到新表生成为歀€‚新表生成后,这些更新和修改信息会自动转移到新表上ã€�
注意,如果您在执è¡�ALTER TABLE时使用除äº�RENAME以外的选项,则MySQL会创建一个临时表。即使数据并不需要进行复制(例如当您更改列的名称时)ï¼�MySQL也会这么操作。对äº�MyISAM表,您可以通过æŠ�myisam_sort_buffer_size系统变量设置到一个较高的值,来加快重新创建索引(该操作是变更过程中速度最慢的一部分)的速度ã€�
· 要使ç”�ALTER TABLE,您需要获得表çš�ALTER, INSERTå’�CREATE权限ã€�
· IGNOREæ˜�MySQL相对于标å‡�SQL的扩展。如果在新表中有重复关键字,或者当STRICT模式启动后出现警告,则使ç”�IGNORE控制ALTER TABLE的运行。如果没有指å®�IGNORE,当重复关键字错误发生时,复制操作被放弃,返回前一步骤。如果指定了IGNORE,则对于有重复关键字的行,只使用第一行,其它有冲突的行被删除。并且,对错误值进行修正,使之尽量接近正确值ã€�
· 您可以在一ä¸�ALTER TABLE语句里写入多ä¸�ADD, ALTER, DROPå’�CHANGE子句,中间用逗号分开。这æ˜�MySQL相对于标å‡�SQL的扩展。在标准SQL中,每个ALTER TABLE语句中每个子句只允许使用一次。例如,在一个语句中取消多个列:
· mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
· CHANGE col_name, DROP col_nameå’�DROP INDEXæ˜�MySQL相对于标å‡�SQL的扩展ã€�
· MODIFYæ˜�Oracleå¯�ALTER TABLE的扩展ã€�
· COLUMN只是自选项目,可以忽略ã€�
· 如果您使ç”�ALTER TABLE tbl_name RENAME TO new_tbl_name并且没有其它选项,则MySQL只对ä¸�table tbl_name相对应的文件进行重命名。不需要创建一个临时表。(您也可以使用RENAME TABLE语句对表进行重命名。请参见13.1.9节,“RENAME TABLE语法â€�。)
· column_definition子句使用ä¸�CREATE TABLE中的ADDå’�CHANGE子句相同的语法。注意,此语法包括列名称,而不只是列类型。请参见13.1.5节,“CREATE TABLE语法â€�ã€�
· 您可以使ç”�CHANGE old_col_name column_definition子句对列进行重命名。重命名时,需给定旧的和新的列名称和列当前的类型。例如:要把一ä¸�INTEGER列的名称ä»�a变更åˆ�b,您需要如下操作:
· mysql> ALTER TABLE t1 CHANGE a b INTEGER;
如果您想要更改列的类型而不是名称, CHANGE语法仍然要求旧的和新的列名称,即使旧的和新的列名称是一样的。例如:
mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
您也可以使用MODIFY来改变列的类型,此时不需要重命名ï¼�
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
· 如果您使ç”�CHANGEæˆ�MODITY缩短列长时,列中存在有索引,并且缩短后的列长小于索引长度,则MySQL会自动缩短索引的长度ã€�
· 当您使用CHANGEæˆ�MODIFY更改列的类型时,MySQL会尽量把原有的列值转化为新的类型ã€�
· 您可以使ç”�FIRSTæˆ�AFTER col_name在一个表行中的某个特定位置添加列。默认把列添加到最后。您也可以在CHANGEæˆ�MODIFY语句中使ç”�FIRSTå’�AFTERã€�
· AFTER COLUMN用于指定列的新默认值,或删除旧的默认值。如果旧的默认值被删除同时列值为NULL,则新的默认值为NULL。如果列值不能为NULLï¼�MySQL会指定一个默认值,请参è§�13.1.5节,“CREATE TABLE语法â€�ã€�
· DROP INDEX用于取消索引。这æ˜�MySQL相对于标å‡�SQL的扩展。请参见13.1.7节,“DROP INDEX语法â€�ã€�
· 如果列从表中被取消了,则这些列也从相应的索引中被取消。如果组成一个索引的所有列均被取消,则该索引也被取消ã€�
· 如果一个表只包含一列,则此列不能被取消。如果您想要取消表,应使ç”�DROP TABLEã€�
· DROP PRIMAY DEY用于取消主索引。注释:åœ�MySQL较早的版本中,如果没有主索引,则DROP PRIMARY KEY会取消表中的第一ä¸�UNIQUE索引。在MySQL 5.1中不会出现这种情况。如果在MySQL 5.1中对没有主键的表使用DROP PRIMARY KEY,则会出现错误信息ã€�
如果您向表中添加UNIQUE KEYæˆ�PRIMARY KEY,则UNIQUE KEYæˆ�PRIMARY KEY会被储存在非唯一索引之前,这æ �MySQL就可以尽早地检查出重复关键字ã€�
· ORDER BY用于在创建新表时,让各行按一定的顺序排列。注意,在插入和删除后,表不会仍保持此顺序。当您知道多数情况下您会按照特定的顺序查询各行时,可以使用这个选项;在对表进行了大的改动后,通过使用此选项,您可以提高查询效率。在有些情况下,如果表按列排序,对于MySQL来说,排序可能会更简单ã€�
· 如果您对一ä¸�MyISAM表使ç”�ALTER TABLE,则所有非唯一索引会被创建到一个单独的批里(和REPAIR TABLE相同)。当您有许多索引时,这样做可以使ALTER TABLE的速度更快ã€�
这项功能可以明确激活ã€�ALTER TABLE...DISABLE KEYSè®�MySQL停止更新MyISAM表中的非唯一索引。然后使ç”�ALTER TABLE ... ENABLE KEYS重新创建丢失的索引。进行此操作时,MySQL采用一种特殊的算法,比一个接一个地插入关键字要快很多。因此,在进行成批插入操作前先使关键字禁用可以大大地加快速度。使ç”�ALTER TABLE ... DISABLE KEYS除了需要获得以前提到的权限以外,还需要获å¾�INDEX权限ã€�
· Innodb存储引擎支持FOREIGN KEYå’�REFERENCES子句ã€�Innodb存储引擎执行ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...)。请参见15.2.6.4节,“FOREIGN KEY约束â€�。对于其它存储引擎,这些子句会被分析,但是会被忽略。对于所有的存储引擎ï¼�CHECK子句会被分析,但是会被忽略。请参见13.1.5节,“CREATE TABLE语法â€�。接受这些子句但又忽略子句的原因是为了提高兼容性,以便更容易地从其å®�SQL服务器中导入代码,并运行应用程序,创建带参考数据的表。请参见1.8.5节,“MySQL与标准SQL的差别â€�ã€�
· InnoDB支持使用ALTER TABLE来取消外键:
· ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;
要了解更多信息,请参è§�15.2.6.4节,“FOREIGN KEY约束â€�ã€�
· ALTER TABLE忽略DATA DIRECTORYå’�INDEX DIRECTORY表选项ã€�
· 如果您想要把表默认的字符集和所有字符列ï¼�CHAR, VARCHAR, TEXT)改为新的字符集,应使用如下语句ï¼�
· ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;
警告:前面的操作转换了字符集之间的列类型。如果您有一列使用一种字符集(如latin1),但是存储的值实际上使用了其它的字符集(å¦�utf8),这种情况不是您想要的。此时,您必须对这样的列进行以下操作ã€�
ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
这种方法能够实现此功能的原因是,当您转换åˆ�BLOB列或ä»�BLOB列转换过来时,并没有发生转换ã€�
如果您指å®�CONVERT TO CHARACTER SET为二进制,则TEXT列被转换到相应的二进制字符串类型ï¼�BINARY, VARBINARY, BLOB)。这意味着这些列将不再有字符集,接下来çš�CONVERT TO操作也将不适用于这些列ã€�
要仅仅改变一个表的默认字符集,应使用此语句:
ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;
词语DEFAULT为自选项。如果您在向表中添加一个新列时(例如,使用ALTER TABLE...ADD column)没有指定字符集,则此时使用的字符集为默认字符集ã€�
警告ï¼�ALTER TABLE...DEFAULT CHARACTER SETå’�ALTER TABLE...CHARACTER SET是等价的,只用于更改默认的表字符集ã€�
· 如果InnoDB表在创建时,使用äº�.ibd文件中的自己的表空间,则这样的文件可以被删除和导入。使用此语句删除.ibd文件ï¼�
· ALTER TABLE tbl_name DISCARD TABLESPACE;
此语句用于删除当前的.ibd文件,所以应首先确认您有一个备份。如果在表空间被删除后尝试打开表格,则会出现错误ã€�
要把备份çš�.ibd文件还原到表中,需把此文件复制到数据库目录中,然后书写此语句:
ALTER TABLE tbl_name IMPORT TABLESPACE;
è§�15.2.6.6节,“使用按表的表空间â€�ã€�
· 使用mysql_info() C API函数,您可以了解有多少记录已被复制,以及(当使用IGNORE时)有多少记录由于重复关键字的原因已被删除。请参见25.2.3.34节,“mysql_info()â€�ã€�
· ALTER TABLE也可以用于对带分区的表进行重新分区,功能包括添加、取消、合并和拆分各分区,还可以用于进行分区维护ã€�
对带分区的表使用partition_options子句å’�ALTER TABLE可以对表进行重新分区,使用时依据partition_options定义的分区方法。本子句ä»�PARTITION BY为开头,然后使用与用äº�CREATE TABLEçš�partition_options子句一样的语法和规则(要了解详细信息,请参è§�13.1.5节,“CREATE TABLE语法â€�)。注释:MySQL 5.1服务器目前接受此语法,但是不实际执行;等MySQL 5.1开发出来后,将执行此语法ã€�
用于ALTER TABLE ADD PARTITIONçš�partition_definition子句支持用于CREATE TABLE语句çš�partition_definition子句的同样名称的选项。(要了解语法和介绍,请参见13.1.5节,“CREATE TABLE语法â€�。)例如,假设您有一个按照以下方式创建的带分区的表:
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)
);
您可以在表中增加一个新的分åŒ�p3,该分区用于储存小于2002的值。添加方法如下:
ALTER TABLE t1 ADD PARTITION p3 VALUES LESS THAN (2002);
注释:您不能使用ALTER TABLE向一个没有进行分区的表添加分区ã€�
DROP PARTITION用于取消一个或多个RANGEæˆ�LIST分区。此命令不能用于HASHæˆ�KEY 分区;用于这两个分区时,应使ç”�COALESCE PARTITION(见后)。如果被取消的分区其名称列于partition_names清单中,则储存在此分区中的数据也被取消。例如,如果以前已定义的è¡�t1,您可以采用如下方法取消名称ä¸�p0å’�p1的分区:
ALTER TABLE DROP PARTITION p0, p1;
ADD PARTITIONå’�DROP PARTITION目前不支æŒ�IF [NOT] EXISTS。也不可能对一个分区或一个已分区的表进行重命名。如果您希望对一个分区进行重命名,您必须取消分区,再重新建立;如果您希望对一个已分区的表进行重新命名,您必须取消所有分区,然后对表进行重命名,再添加被取消的分区ã€�
COALESCE PARTITION可以用于使用HASHæˆ�KEY进行分区的表,以便使ç”�number来减少分区的数目。例如,假设您使用下列方法创建了è¡�t2ï¼�
CREATE TABLE t2 (
name VARCHAR (30),
started DATE
)
PARTITION BY HASH(YEAR(started))
PARTITIONS (6);
您可以使用以下命令,æŠ�t2使用的分区的数目ç”�6个减少到4个:
ALTER TABLE t2 COALESCE PARTITION 2;
包含在最后一ä¸�number分区中的数据将被合并到其余的分区中。在此情况下,分åŒ�4和分åŒ�5将被合并到前4个分区中(编号为0ã€�1ã€�2å’�3的分区)ã€�
如果要更改部分分区,但不更改所有的分区,您可以使用REORGANIZE PARTITION。这个命令有多种使用方法ï¼�
o 把多个分区合并为一个分区。通过把多个分区的名称列入partition_names清单,并ä¸�partition_definition提供一个单一的定义,可以实现这个功能ã€�
o 把一个原有的分区拆分为多个分区。通过ä¸�partition_names命名一个分区,并提供多ä¸�partition_definitions,可以实现这个功能ã€�
o 更改使用VALUES LESS THAN定义的分区子集的范围或更改使ç”�VALUES IN定义的分区子集的值清单ã€�
注释:对于没有明确命名的分区ï¼�MySQL会自动提供默认名ç§�p0, p1, p2等ã€�
要了解有å…�ALTER TALBE...REORANIZE PARTITION命令的详细信息,请参è§�18.3节,“分区管理â€�ã€�
· 多个附加子句用于提供分区维护和修补功能。这些功能与用于非分区表的功能类似。这些功能由CHECK TABLEå’�REPAIR TABLE等命令(这些命令不支持用于分区表)执行。这些子句包æ‹�ANALYZE PARTITION, CHECK PARTITION, OPTIMIZE PARTITION, REBUILD PARTITIONå’�REPAIR PARTITION.每个选项均为一ä¸�partition_names子句,包括一个或多个分区名称。需要更改的表中必须已存在这些分区。多个分区名称用逗号分隔。要了解更多信息,或要了解举例说明,请参è§�18.3.3节,“分区维护â€�ã€�
以下例子展示äº�ALTER TABLE的使用。首先展示表t1。表t1采用如下方法创建ï¼�
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
把表t1重新命名ä¸�t2ï¼�
mysql> ALTER TABLE t1 RENAME t2;
把列aä»�INTERGER更改ä¸�TINYINT NOT NULL(名称保持不变),并把列bä»�CHAR(10)更改ä¸�CHAR(20),同时把åˆ�b重新命名为列cï¼�
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
添加一个新çš�TIMESTAMP列,名称ä¸�dï¼�
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
在列d和列a中添加索引:
mysql> ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);
删除åˆ�cï¼�
mysql> ALTER TABLE t2 DROP COLUMN c;
添加一个新çš�AUTO_INCREMENT整数列,名称ä¸�cï¼�
mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
-> ADD PRIMARY KEY (c);
注意我们ä¸�c编制了索引(作为PRIMARY KEY),因为AUTO_INCREMENT列必须编制索引。同时我们定ä¹�cä¸�NOT NULL,因为主键列不能ä¸�NULLã€�
当您添加一ä¸�AUTO_INCREMENT列时,列值被自动地按序号填入。对äº�MyISAM表,您可以在ALTER TABLE之前执行SET INSERT_ID=value来设置第一个序号,也可以使ç”�AUTO_INCREMENT=value表选项来设置。请参见13.5.3节,“SET语法â€�ã€�
如果值大äº�AUTO_INCREMENT列中的最大值,则您可以使用用于InnoDB表的ALTER TALBE...AUTO_INCREMENT=value表选项,来为新行设置序号。如果值小于列中当前的最大值,不会出现错误信息,当前的序列值也不改变ã€�
使用MyISAM表时,如果您不更æ”�AUTO_INCREMENT列,则序列号不受影响。如果您取消一ä¸�AUTO_INCREMENT列,然后添加另一ä¸�AUTO_INCREMENT列,则序号重新排列,ä»�1开始ã€�
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用于创建数据库,并进行命名。如果要使用CREATE DATABASE,您需要获得数据库CREATE权限ã€�
有关合法数据库名称的规定列于9.2节,“数据库、表、索引、列和别名â€�。如果存在数据库,并且您没有指定IF NOT EXISTS,则会出现错误ã€�
create_specification选项用于指定数据库的特性。数据库特性储存在数据库目录中çš�db.opt文件中ã€�CHARACTER SET子句用于指定默认的数据库字符集ã€�COLLATE子句用于指定默认的数据库整序。字符集和整序名称在ç¬�10ç«�ï¼�字符集支æŒ�中讨论ã€�
有些目录包含文件,这些文件与数据库中的表对应ã€�MySQL中的数据库的执行方法与这些目录的执行方法相同。因为当数据库刚刚被创建时,在数据库中没有表,所ä»�CREATE DATABASE只创建一个目录。这个目录位äº�MySQL数据目录å’�db.opt文件之下ã€�
如果您手动在数据目录之下创建一个目录(例如,使ç”�mkdir),则服务器会认为这是一个数据库目录,并åœ�SHOW DATABASES的输出中显示出来ã€�
也可以使ç”�CREATE SCHEMAã€�
您还可以使用mysqladmin程序创建数据库。请参见8.5节,“mysqladmin:用于管理MySQL服务器的客户端â€�ã€�
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被映射到一ä¸�ALTER TABLE语句上,用于创建索引。请参见13.1.2节,“ALTER TABLE语法â€�ã€�
通常,当使用CREATE TABLE创建表时,也同时在表中创建了所有的索引。请参见13.1.5节,“CREATE TABLE语法â€�ã€�CREATE INDEX允许您向已有的表中添加索引ã€�
格式为(col1, col2,...)的一个列清单创建出一个多列索引。通过串接给定列中的值,确定索引值的格式ã€�
对于CHARå’�VARCHAR列,只用一列的一部分就可创建索引。创建索引时,使ç”�col_name(length)语法,对前缀编制索引。前缀包括每列值的å‰�lengthä¸�字符ã€�BLOBå’�TEXT列也可以编制索引,但是必须给出前缀长度ã€�
此处展示的语句用于创建一个索引,索引使用列名称的å‰�10个字符ã€�
CREATE INDEX part_of_name ON customer (name(10));
因为多数名称的前10个字符通常不同,所以此索引不会比使用列的全名创建的索引速度慢很多。另外,使用列的一部分创建索引可以使索引文件大大减小,从而节省了大量的磁盘空间,有可能提é«�INSERT操作的速度ã€�
前缀最长为255字节。对äº�MyISAMå’�InnoDB表,前缀最长为1000字节。注意前缀的限长以字节计,è€�CREATE INDEX语句中的前缀长度指的是字符的数目。对于使用多字节字符集的列,在指定列的前缀长度时,要考虑这一点ã€�
åœ�MySQL 5.1中:
· 只有当您正在使用MyISAM, InnoDBæˆ�BDB表类型时,您可以向有NULL值的列中添加索引ã€�
· 只有当您正在使用MyISAM, BDBæˆ�InnoDB表类型时,您可以å��BLOBæˆ�TEXT列中添加索引ã€�
一ä¸�index_col_name规约可以ä»�ASCæˆ�DESC为结尾。这些关键词将来可以扩展,用于指定递增或递减索引值存储。目前,这些关键词被分析,但是被忽略;索引值均以递增顺序存储ã€�
部分储存引擎允许在创建索引时指定索引类型ã€�index_type指定语句的语法是USING type_name。不同的储存引擎所支持çš�type_name值已显示在下表中。如果列有多个索引类型,当没有指å®�index_type时,第一个类型是默认å€�ã€�
|
存储引擎 |
允许的索引类åž� |
|
MyISAM |
BTREE |
|
InnoDB |
BTREE |
|
MEMORY/HEAP |
HASH, BTREE |
示例ï¼�
CREATE TABLE lookup (id INT) ENGINE = MEMORY;
CREATE INDEX id_index USING BTREE ON lookup (id);
TYPE type_name可以作为USING type_name的同义词,用于指定索引类型。但是,USING是首选的格式。另外,在索引规约语法中,位于索引类型前面的索引名称不能使用TYPE。这是因为,ä¸�USING不同ï¼�TYPE不是保留词,因此会被认为是一个索引名称ã€�
如果您指定的索引类型在给定的储存引擎中不合法,但是有其它的索引类型适合引擎使用,并且不会影响查询功能,则引擎应使用此类型ã€�
要了解更多有å…�MySQL如何使用索引的信息,请参è§�7.4.5节,“MySQL如何使用索引â€�ã€�
FULLTEXT索引只能å¯�CHAR, VARCHARå’�TEXT列编制索引,并且只能åœ�MyISAM表中编制。请参见12.7节,“全文搜索功能â€�ã€�
SPATIAL索引只能对空间列编制索引,并且只能在MyISAM表中编制。空间列类型åœ�ç¬�19章:MySQL中的空间扩展中进行了描述ã€�
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(create_definition,...)]
[table_options] [select_statement]
或:
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用于创建带给定名称的表。您必须拥有è¡�CREATE权限ã€�
允许的表名称的规则列äº�9.2节,“数据库、表、索引、列和别名â€�中。默认的情况是,表被创建到当前的数据库中。如果表已存在,或者如果没有当前数据库,或者如果数据库不存在,则会出现错误ã€�
表名称被指定ä¸�db_name.tbl_name,以便在特定的数据库中创建表。不论是否有当前数据库,都可以通过这种方式创建表。如果您使用加引号的识别名,则应对数据库和表名称分别加引号。例如,`mydb`.`mytbl`是合法的,但æ˜�`mydb.mytbl`不合法ã€�
在创建表格时,您可以使用TEMPORARY关键词。只有在当前连接情况下,TEMPORARY表才是可见的。当连接关闭时,TEMPORARY表被自动取消。这意味着两个不同的连接可以使用相同的临时表名称,同时两个临时表不会互相冲突,也不与原有的同名的非临时表冲突。(原有的表被隐藏,直到临时表被取消时为歀€‚)您必须拥æœ�CREATE TEMPORARY TABLES权限,才能创建临时表ã€�
如果表已存在,则使用关键è¯�IF NOT EXISTS可以防止发生错误。注意,原有表的结构ä¸�CREATE TABLE语句中表示的表的结构是否相同,这一点没有验证。注释:如果您在CREATE TABLE...SELECT语句中使ç”�IF NOT EXISTS,则不论表是否已存在,由SELECT部分选择的记录都会被插入ã€�
MySQL通过数据库目录中çš�.frm表格式(定义)文件表示每个表。表的存储引擎也可能会创建其它文件。对äº�MyISAM表,存储引擎可以创建数据和索引文件。因此,对于每个MyISAMè¡�tbl_name,有三个磁盘文件ï¼�
|
文件 |
作用 |
|
tbl_name.frm |
表格式(定义)文ä»� |
|
tbl_name.MYD |
数据文件 |
|
tbl_name.MYI |
索引文件 |
用于表示表的由存储引擎创建的文件åœ�ç¬�15章:存储引擎和表类型中描述ã€�
要了解有关各种列类型的性质的一般说明,请参è§�ç¬�11章:列类åž�。要了解有关空间列类型的说明,请参见ç¬�19章:MySQL中的空间扩展ã€�
· 如果没有指定æ˜�NULL或是NOT NULL,则列在创建时假定指定为NULLã€�
· 一个整数列可以拥有一个附加属æ€�AUTO_INCREMENT。当您向一个已编入索引çš�AUTO_INCREMENT列中插入一ä¸�NULL值(建议)或0时,此列被设置为下一个序列的值。通常情况下为value+1,此å¤�value是当前在表中的列的最大值ã€�AUTO_INCREMENT序列ä»�1开始。这样的列必须被定义为一种整数类型,请参è§�11.1.1节,“数值类型概述â€�中的叙述。(å€�1.0不是整数)。请参见25.2.3.36节,“mysql_insert_id()â€�ã€�
ä¸�--sql-mode服务器选项æˆ�sql_mode系统变量指定NO_AUTO_VALUE_ON_ZERO特征位,这样可以æŠ�0存储åˆ�AUTO_INCREMENT列中,同时不生成一个新的序列值。请参见5.3.1节,â€�mysqld命令行选项â€�ã€�
注释:有时候,每个表只有一ä¸�AUTO_INCREMENT列,此列必须编制索引,不能有DEFAULT值。一ä¸�AUTO_INCREMENT列只有在只包含正数的情况下,才能运行正常。插入一个负数会被认为是插入了一个非常大的正数。这样做是为了避免当数字由正数转为负数时出现精度问题,同时也为了确保AUTO_INCREMENT列中不会包含0ã€�
对于MyISAMå’�BDB表,您可以在一个多列关键字中指定一ä¸�AUTO_INCREMENT次级列。请参见3.6.9节,“使用AUTO_INCREMENTâ€�ã€�
为了è®�MySQL与部åˆ�ODBC应用软件相兼容,您可以使用以下查询方法找到最后一个插入行çš�AUTO_INCREMENT值:
SELECT * FROM tbl_name WHERE auto_col IS NULL
· 字符列的定义可以包括一ä¸�CHARACTER SET属性,用来指定字符集,也可以指定列的整序。要了解详细情况,请参见ç¬�10章:字符集支æŒ�ã€�CHARSETæ˜�CHARACTER SET的同义词ã€�
· CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);
MySQL 5.1理解,在字符列定义中的长度规约以字符为单位。(有些早期版本以字节为单位。)
· DEFAULT子句用于为列指定一个默认值。默认值必须为一个常数,不能为一个函数或一个表达式,有一种情况例外。例如,一个日期列的默认值不能被设置为一个函数,å¦�NOW()æˆ�CURRENT_DATE。不过,有一种例外,您可以对TIMESTAMP列指å®�CURRENT_TIMESTAMP为默认值。请参见11.3.1.1节,“MySQL 4.1中的TIMESTAMP属性â€�ã€�
BLOBå’�TEXT列不能被赋予默认值ã€�
如果在列定义中没有明确的DEFAULT值,åˆ�MySQL按照如下规则确定默认值:
如果列可以使ç”�NULL作为值,则使ç”�DEFAULT NULL子句对列进行定义。(åœ�MySQL的早期版本中也如此。)
如果列不能使ç”�NULL作为值,åˆ�MySQL对列进行定义时不使用DEFAULT子句。输入数据时,如æž�INSERTæˆ�REPLACE语句不包括列的值,åˆ�MySQL依据当时的有效的SQL模式操作列:
o 如果严格模式没有被启用,åˆ�MySQL会根据列数据类型,把列设置为明确的默认值ã€�
o 如果严格模式已被启用,则事务表会出现错误,语句被回滚。对于非事务表,会出现错误,不过,如果错误出现在一个多行语句中的第二行或后续行,则以前的各行将被插入ã€�
假设è¡�t按下面的方法进行定义ï¼�
CREATE TABLE t (i INT NOT NULL);
在这种情况下ï¼�i没有明确的默认值,所以在严格模式中,每个后续语句都会产生一个错误,并且没有行被插入。当未使用严格模式时,只有第三个语句产生错误;明确的默认值被插入到前两个语句中,但是第三个语句会出现错误,因ä¸�DEFAULT(i)不会产生一个值:
INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));
è§�5.3.2节,“SQL服务器模式â€�ã€�
对于一个给定的表,您可以使ç”�SHOW CREATE TABLE语句来查看那些列有明确的DEFAULT子句ã€�
· 对于列的评注可以使用COMMENT选项来进行指定。评注通过SHOW CREATE TABLEå’�SHOW FULL COLUMNS语句显示ã€�
· 属æ€�SERIAL可以用作BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的别名ã€�
· KEY通常æ˜�INDEX同义词。如果关键字属æ€�PRIMARY KEY在列定义中已给定,则PRIMARY KEY也可以只指定ä¸�KEY。这么做的目的是与其它数据库系统兼容ã€�
· åœ�UNIQUE索引中,所有的值必须互不相同。如果您在添加新行时使用的关键字与原有行的关键字相同,则会出现错误。例外情况是,如果索引中的一个列允许包含NULL值,则此列可以包含多ä¸�NULL值。此例外情况不适用äº�BDB表。在BDB中,带索引的列只允许一个单一NULLã€�
· PRIMARY KEY是一个唯一KEY,此时,所有的关键字列必须定义ä¸�NOT NULL。如果这些列没有被明确地定义ä¸�NOT NULLï¼�MySQL应隐含地定义这些列。一个表只有一ä¸�PRIMARY KEY。如果您没有PRIMARY KEY并且一个应用程序要求在表中使用PRIMARY KEY,则MySQL返回第一ä¸�UNIQUE索引,此索引没有作为PRIMARY KEYçš�NULL列ã€�
· 在已创建的表中,PRIMARY KEY的位置最靠前,然后是所有的UNIQUE索引,然后是非唯一索引。这可以帮助MySQL优化程序选择优先使用哪个索引,并且更快速的检测出重复çš�UNIQUE关键字ã€�
· PRIMARY KEY可以是一个多列索引。但是,在列规约中使ç”�PRIMARY KEY关键字属性无法创建多列索引。这么做只能把一个列标记为主列。您必须使用一个单独的PRIMARY KEYï¼�index_col_name, ...)子句ã€�
· 如果PRIMARY KEYæˆ�UNIQUE索引只包括一个列,并且此列为整数类型,则您也可以åœ�SELECT语句中把此列作为_rowid引用ã€�
· åœ�MySQL中,PRIMARY KEY的名称为PRIMARY。对于其它索引,如果您没有赋予名称,则索引被赋予的名称与第一个已编入索引的列的名称相同,并自选添加后缀ï¼�_2, _3,...),使名称为唯一名称。您可以使用SHOW INDEX FROM tbl_name来查看表的索引名称。请参见13.5.4.11节,“SHOW INDEX语法â€�ã€�
· 部分存储引擎允许您在创建索引时指定索引类型ã€�index_type指示语句的语法是USING type_nameã€�
示例ï¼�
CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;
要了解有å…�USING的详细说明,请参è§�13.1.4节,“CREATE INDEX语法â€�ã€�
要了解有å…�MySQL如何使用索引的更多信息,请参è§�7.4.5节,“MySQL如何使用索引â€�ã€�
· åœ�MySQL 5.1中,只有MyISAMï¼�InnoDB, BDBå’�MEMORY存储引擎支持在含æœ�NULL值的列中编索引。在其它情况下,您必须定义已编索引的列为NOT NULL,否则会出现错误ã€�
· 在一个索引规约中使用col_name(length)语法,您可以创建一个索引,此索引只使用一ä¸�CHARæˆ�VARCHAR列的第一ä¸�length字符。只对列值的前缀编制索引可以使索引文件大大减小。请参见7.4.3节,“列索引â€�ã€�
MyISAMå’�InnoDB存储引擎也支持对BLOBå’�TEXT列编索引。当å¯�BLOBæˆ�TEXT列编索引时,您必须为索引指定一个前缀长度。例如:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
对于MyISAMå’�InnoDB表,前缀最长可以为1000字节,对于其它表格类型,最长可以为255字节。注意前缀长度限值以字节为单位,而在CREATE TABLE语句中的前缀长度用字符数目来表述。当为一个使用多字节字符集的列指定前缀长度时,一定要考虑到这一点ã€�
· 一ä¸�index_col_name规约可以ä»�ASCæˆ�DESC结尾。这些关键词可以在将来进行扩展,用于指定升序或降序的索引值存储。当前,这些关键词被分析但是被忽略;索引值均以升序储存ã€�
·
当您åœ�SELECT中的TEXT列或BLOB列中使用ORDER
BYæˆ�GROUP BY时,服务器只使用初始的字节数目对值进行分类。字节数目由max_sort_length系统变量进行指示。请参见11.4.3节,“BLOB和TEXT类型â€�ã€�
· 您可以创建特殊的FULLTEXT索引,用于全文搜紀€‚只æœ�MyISAM表类型支æŒ�FULLTEXT索引ã€�FULLTEXT索引只可以从CHAR, VARCHARå’�TEXT列中创建。整个列都会被编入索引;不支持对部分列编索引。如果已指定,前缀长度会被忽略。要了解运行的详细说明,请参è§�12.7节,“全文搜索功能â€�ã€�
· 您可以为空间列类型创å»�SPATIAL索引。只æœ�MyISAM表支持空间类型,已编索引的列必须声明ä¸�NOT NULL。请参见ç¬�19章:MySQL中的空间扩展ã€�
· InnoDB表支持对外键限制条件进行检查。请参见15.2节,“InnoDB存储引擎â€�。注意,åœ�InnoDB中,FOREIGN KEY语法比本节开始时介绍çš�CREATE TABLE语句的语法更严格:被引用的表中的列必须有明确的命名ã€�InnoDB支持外键çš�ON DELETEå’�ON UPDATE两种操作。有关精确语法的说明,请参见15.2.6.4节,“FOREIGN KEY约束â€�ã€�
对于其它存储引擎ï¼�MySQL服务器对CREATE TABLE语句中的FOREIGN KEYå’�REFERENCES语法进行分析,但不采取进一步的行动。所有的存储引擎均对CHECK子句进行分析,但是忽ç•�CHECK子句。请参见1.8.5.5节,“外键â€�ã€�
· 对于MyISAM表,每个NULL列要多占用一位,进位到距离最近的字节。最大记录长度(以字节为单位)按照如下方法计算:
· row length = 1
· + (sum of column lengths)
· + (number of NULL columns + delete_flag + 7)/8
· + (number of variable-length columns)
对于采用静态记录格式的表,delete_flagä¸�1。静态表在行记录中使用一位用作位标记。位标记指示该行是否已被删除。对于动态表ï¼�delete_flagä¸�0,因为在动态行标题中已存储了位标记ã€�
这些计算方法不适用äº�InnoDB表。对äº�InnoDB表,NULL列的存储量与NOT NULL列的存储量没有区别ã€�
ENGINEå’�TYPE选项用于为表指定存储引擎ã€�ENGINE是首选的选项名称ã€�
ENGINEå’�TYPE选项采用以下值:
|
存储引擎 |
说明 |
|
ARCHIVE |
档案存储引擎。请参见15.8节,“ARCHIVE存储引擎â€�ã€� |
|
BDB |
带页面锁定的事务安全表。也称为BerkeleyDB。请参见15.5节,“BDB (BerkeleyDB)存储引擎â€�ã€� |
|
CSV |
值之间用逗号隔开的表。请参见15.9节,“CSV存储引擎ã€� |
|
EXAMPLE |
示例引擎。请参见15.6节,“EXAMPLE存储引擎â€�ã€� |
|
FEDERATED |
可以访问远程表的存储引擎。请参见15.7节,“FEDERATED存储引擎â€�ã€� |
|
HEAP |
|
|
(OBSOLETE) ISAM |
åœ�MySQL 5.1中没有此引擎。如果您要从以前的版本升级到MySQL 5.1,您应该在进行升级前把原有的ISAM表转换为MyISAM表。请参见ç¬�15章:存储引擎和表类型ã€� |
|
InnoDB |
带行锁定和外键的事务安全表。请参见15.2节,“InnoDB存储引擎â€�ã€� |
|
MEMORY |
本表类型的数据只保存在存储器里。(在早æœ�MySQL版本中被称为HEAP。) |
|
MERGE |
MyISAM表的集合,作为一个表使用。也称为MRG_MyISAM。请参见15.3节,“MERGE存储引擎â€�ã€� |
|
MyISAM |
二进制轻便式存储引擎,此引擎æ˜�MySQL所用的默认存储引擎。请参见15.1节,“MyISAM存储引擎â€�ã€� |
|
NDBCLUSTER |
要了解有å…�MySQL存储引擎的更多信息,请参è§�ç¬�15章:存储引擎和表类型ã€�
如果被指定的存储引擎无法利用,则MySQL使用MyISAM代替。例如,一个表定义包括ENGINE=BDB选项,但æ˜�MySQL服务器不支持BDB表,则表被创建为MyISAM表。这样,如果您在主机上有事务表,但在从属机上创建的是非交互式表(以加快速度)时,可以进行复制设置。在MySQL 5.1中,如果没有遵守存储引擎规约,则会出现警告ã€�
其它表选项用于优化表的性质。在多数情况下,您不必指定表选项。这些选项适用于所有存储引擎,另有说明除外ï¼�
· AUTO_INCREMENT
表的初始AUTO_INCREMENT值。在MySQL 5.1中,本选项只适用äº�MyISAMå’�MEMORY表ã€�InnoDB也支持本选项。如果引擎不支持AUTO_INCREMENT表选项,则要设置引擎的第一ä¸�auto-increment值,需插入一个“假”行。该行的值比创建表后的值小一,然后删除该假行ã€�
对于åœ�CREATE TABLE语句中支æŒ�AUTO_INCREMENT表选项的引擎,您也可以使用ALTER TABLE tbl_name AUTO_INCREMENT = n来重新设ç½�AUTO_INCREMENT值ã€�
· AVG_ROW_LENGTH
表中平均行长度的近似值。只需要对含尺寸可变的记录的大型表进行此项设置ã€�
当创建一ä¸�MyISAM表时ï¼�MySQL使用MAX_ROWSå’�AVG_ROW_LENGTH选项的乘积来确定得出的表有多大。如果有一个选项未指定,则表的最大尺寸为65,536TB数据。(如果操作系统不支持这么大的文件,则表的尺寸被限定在操作系统的限值处。)如果您想缩小指针尺寸使索引更小,速度更快,并且您不需要大文件,则您可以通过设置myisam_data_pointer_size系统变量来减少默认指针的尺寸。(è§�5.3.3节,“服务器系统变量â€�。)如果您希望所有的表可以扩大,超过默认限值,并且愿意让表稍微慢点,并稍微大点,则您可以通过设置此变量增加默认指针的尺寸ã€�
· [DEFAULT] CHARACTER SET
用于为表指定一个默认字符集ã€�CHARSETæ˜�CHARACTER SET的同义词ã€�
对于CHARACTER SET.
· COLLATE
用于为表指定一个默认整序ã€�
· CHECKSUM
如果您希æœ�MySQL随时对所有行进行实时检验求和(也就是,表变更后ï¼�MySQL自动更新检验求和),则应把此项设置ä¸�1。这样做,表的更新速度会略微慢些,但是更容易寻找到受损的表ã€�CHECKSUM TABLE语句用于报告检验求和(仅限äº�MyISAM)ã€�
· COMMENT
表的注释,最é•�60个字符ã€�
· CONNECTION
FEDERATED表的连接字符串。( 注释:较早版本的MySQL使用COMMENT选项用于连接字符串ã€�
· MAX_ROWS
您打算储存在表中的行数目的最大值。这不是一个硬性限值,而更像一个指示语句,指示出表必须能存储至少这么多行ã€�
· MIN_ROWS
您打算存储在表中的行数目的最小值ã€�
· PACK_KEYS
如果您希望索引更小,则把此选项设置ä¸�1。这样做通常使更新速度变慢,同时阅读速度加快。把选项设置ä¸�0可以取消所有的关键字压缩。把此选项设置ä¸�DEFAULT时,存储引擎只压缩长çš�CHARæˆ�VARCHAR列(仅限äº�MyISAM)ã€�
如果您不使用PACK_KEYS,则默认操作是只压缩字符串,但不压缩数字。如果您使用PACK_KEYS=1,则对数字也进行压缩ã€�
在对二进制数字关键字进行压缩时,MySQL采用前缀压缩ï¼�
o 每个关键字需要一个额外的字节来指示前一个关键字中有多少字节与下一个关键字相同ã€�
o 指向行的指针以高位字节优先的顺序存储在关键字的后面,用于改进压缩效果ã€�
这意味着,如果两个连续行中有许多相同的关键字,则后续的“相同”的关键字通常只占用两个字节(包括指向行的指针)。与此相比,常规情况下,后续的关键字占用storage_size_for_key + pointer_size(指针尺寸通常ä¸�4)。但是,只有在许多数字相同的情况下,前缀压缩才有好处。如果所有的关键字完全不同,并且关键字不能含æœ�NULL值,则每个关键字要多使用一个字节。(在这种情况中,储存压缩后的关键字的长度的字节与用于标记关键字是否ä¸�NULL的字节是同一字节。)
· PASSWORD
使用密码å¯�.frm文件加密。在标准MySQL版本中,本选项不起任何作用ã€�
· DELAY_KEY_WRITE
如果您想要延迟对关键字的更新,等到表关闭后再更新,则把此项设置为1(仅限于MyISAM)ã€�
· ROW_FORMAT
定义各行应如何储存。当前,此选项只适用äº�MyISAM表。对于静态行或长度可变行,此选项值可以为FIXEDæˆ�DYNAMICã€�myisampack用于把类型设置为COMPRESSED。请参见15.1.3节,“MyISAM表的存储格式â€�ã€�
在默认情况下ï¼�InnoDB记录以压缩格式存储(ROW_FORMAT=COMPACT)。通过指定ROW_FORMAT=REDUNDANT,仍然可以申请用于较早版本的MySQL中的非压缩格式ã€�
· RAID_TYPE
åœ�MySQL 5.0ä¸�,RAID支持被删除了。要了解有关RAID的说明,请参è§�http://dev.mysql.com/doc/refman/4.1/en/create-table.htmlã€�
· UNION
当您想要把一组相同的表当作一个表使用时,采用UNIONã€�UNION仅适用äº�MERGE表。请参见15.3节,“MERGE存储引擎â€�ã€�
对于您映射到一ä¸�MERGE表上的表,您必须拥有SELECT, UPDATEå’�DELETE权限。(注释:以前,所有被使用的表必须位于同一个数据库中,并作ä¸�MERGE表。这些限制不再适用。)
· INSERT_METHOD
如果您希望在MERGE表中插入数据,您必须ç”�INSERT_METHOD指定应插入行的表ã€�INSERT_METHOD选项仅用äº�MERGE表。使ç”�FIRSTæˆ�LAST把行插入到第一个或最后一个表中;或者使ç”�NO,阻止插入行。请参见15.3节,“MERGE存储引擎â€�ã€�
· DATA DIRECTORY, INDEX DIRECTORY
通过使用DATA DIRECTORY='directory'æˆ�INDEX DIRECTORY='directory',您可以指定MyISAM存储引擎放置表格数据文件和索引文件的位置。注意,目录应是通向目录的完整路径(不是相对路径)ã€�
仅当您没有使ç”�--skip-symbolic-links选项时,DATA DIRECTORY, INDEX DIRECTORY才能使用。操作系统必须有一个正在工作的、线程安全的realpath()调用。要了解全面信息,请参见7.6.1.2节,“在Unix平台上使用表的符号链æŽ�”ã€�
· 对于ç”�CREATE TABLE创建的表,可以使ç”�partition_options控制分区。如果使用了partition_options,则其中必须包含至少一ä¸�PARTITION BY子句。本子句包含用于确定分区的函数;该函数会返回一个整值,范围ä»�1åˆ�num。此å¤�num为分区的数目。此函数中可以使用的选项显示在下面的清单中ã€� 要点:在本节开始时介绍的用äº�partition_options的语法中显示的选项,并不是都能用于所有分区类型。要了解各种类型具体的信æ�� ,请参见以下各类型的清单。要了解有关åœ�MySQL中的分区的操作和使用情况的全面说明,以及要了解表创建的示例和ä¸�MySQL分区有关的其它命令,请参è§�ç¬�18章:分区ã€�
o HASHï¼�expr):用于混编一个或多个列,创建一个关键字,用于放置行,并确定行的位置ã€�expr是一个表达式,使用一个或多个表中的列。该表达式可以是任何能够生成单一整值的合法çš�MySQL表达式(包括MySQL函数)。例如,这些都是有效çš�CREATE TABLE语句,语句中使用äº�PARTITION BY HASHï¼�
o CREATE TABLE t1 (col1 INT, col2 CHAR(5))
o PARTITION BY HASH(col1);
o
o CREATE TABLE t1 (col1 INT, col2 CHAR(5))
o PARTITION BY HASH( ORD(col2) );
o
o CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME)
o PARTITION BY HASH ( YEAR(col3) );
VALUES LESS THANæˆ�VALUES IN子句不能å’�PARTITION BY HASH一起使用ã€�
PARTITION BY HASH使用expr被分区数目所除后的余数(也就是模数)。要了解示例和其它信息,请参è§�18.2.3节,“HASH分区â€�ã€�
LENEAR关键词需要一种不同的算法。在这种情况下,通过一次或多次逻辑AND运算得出的结果,计算出存储记录的分区的数目。要了解线形混编的讨论和示例,请参见18.2.3.1节,“LINEAR HASH分区â€�ã€�
o KEY(column_list):与HASH近似,除了有一点不一样,å��MySQL提供了混编函数,以保证均匀的数据分布ã€�column_list自变量只是各列的一个清单。本示例显示了由关键字进行分区的一个简单的表,分为4个分区:
o CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
o PARTITION BY KEY(col3)
o PARTITIONS 4;
采用LINEAR关键词,您可以对由关键字分区的表进行线形分区。这与由HASH进行分区的表格有同样的效果;也就是说,使ç”�&操作符查找分区数目,而不是使用模数(详细说明è§�18.2.3.1节,“LINEAR HASH分区â€�å’�18.2.4节,“KEY分区â€�)。本示例采用了关键字线形分区,用来在5个分区之间分配数据:
CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
PARTITION BY LINEAR KEY(col3)
PARTITIONS 5;
VALUES LESS THANæˆ�VALUES IN子句不能å’�PARTITION BY KEY一起使用ã€�
o RANGE:在此情况下ï¼�expr使用一å¥�VALUES LESS THAN操作ç¬�显示了某一范围内的值。当使用范围分区时,您必须使ç”�VALUES LESS THAN定义至少一个分区ã€�VALUES IN不能和范围分区一起使用ã€�
VALUES LESS THAN可以与一个文字值同时使用,或者与一个可以求算单一值的表达式同时使用ã€�
举例说明,假设您有一个表,您希望采用以下方法对包含年份值的一列进行分区:
|
分区编号ï¼� |
年份范围ï¼� |
|
0 |
1990以前 |
|
1 |
1991 - 1994 |
|
2 |
1995 - 1998 |
|
3 |
1999 - 2002 |
|
4 |
2003 - 2005 |
|
5 |
2006年以å�� |
采用这种分区方法的表可以通过如下CREATE TABLE语句实现ï¼�
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 ...语句按顺序执行ã€�VALUES LESS THAN MAXVALUE的作用是指定大于最大值的“其余”的值ã€�
注意ï¼�VALUES LESS THAN子句按顺序执行,执行方式类似äº�switch ... case语段的一部分(许多编程语言,如C, Javaå’�PHP也如此)。也就是说,子句必须按照这样一种方法排列,每一个后续的VALUES LESS THAN中指定的上限值大于前一ä¸�VALUES LESS THAN中指定的上限值,并在清单的最后加一个参照性的MAXVALUEã€�
VALUES IN与一系列的值同时使用。举例说明,您可以创建如下的分区方法ï¼�
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)
);
当前,与VALUES IN...同时使用的值必须只包含整数值ã€�
(因为此表只使用VALUES IN表达式进行分区,您也可以ç”�PARTITION BY LIST代替,而不是使ç”�PARTITION BY RANGE。请参见下一条。)
在使ç”�VALUES LESS THANæˆ�VALUES IN情况下,每个分区使用PARTITION name定义,此å¤�name是分区的标识名,后面æŽ�VALUES...子句ã€�
o LIST(expr):当根据含有一系列限定性值(例如州代码或国家代码)的列进行分区时使用。在这种情况下,所有与特定的州或国家有关的记录都被分配到一个单一分区中,或者可以预留出一个分区,用于一系列特定的州或国家ã€�LIST(expr)ä¸�RANGE类似,除了一点以外,即只æœ�VALUES IN可以被用于为每个分区指定值ã€�
当使用清单分区时,您必须使用VALUES IN定义至少一个分区ã€�VALUES LESS THAN不能ä¸�PARTITION BY LIST一起使用ã€�
o 分区数目可以使用PARTITION num子句,自选进行指定,此处ï¼�num是分区的数目。如果本子句和其å®�PARTITION子句同时使用,则num必须与使ç”�PARTITION子句说明的分区的总数相等ã€�
注释:不论您在创建一个由RANGEæˆ�LIST进行分区的表时是否使用了PARTITIONS子句,您必须在表定义中包括至少一ä¸�PARTITION VALUES(见后)ã€�
o 一个分区可以自选分隔成多个子分区。使用自选的SUBPARTITION BY子句可以指示。子分区可以ç”�HASHæˆ�KEY进行分隔。两种方法建立的子分区均ä¸�LINEAR。分隔子分区时的操作方式与以前描述的分区类型的操作方式一样。(无法ç”�LISTæˆ�RANGE进行子分区分隔。)
使用SUBPARTITIONS关键词,后面接一个整值,可以对子分区的数目进行指示ã€�
· 使用一ä¸�partition_definition子句可以对每个分区分别进行定义。下面是组成这个子句的各个部分:
o PARTITION partition_name:用于为分区指定一个逻辑名称ã€�
o VALUE子句:对于范围分区,每个分区必须包括一ä¸�VALUES LESS THAN子句;对于清单分区,您必须为每个分区指定一ä¸�VALUES IN子句。本子句用于确定哪些行将被存储到此分区中。要了解语法示例,请参见ç¬�18章:分区中对分区类型的讨论ã€�
o 自选的COMMENT子句可以用于描述分区。注释必须加单引号。举例说明:
o COMMENT = 'Data for the years previous to 1999'
o DATA DIRECTORYå’�INDEX DIRECTORY可以被用于指示本分区的数据和索引各自的存储位置的目录ã€�data_dirå’�index_dir都必须是绝对系统路径。例如:
o CREATE TABLE th (id INT, name VARCHAR(30), adate DATE)
o PARTITION BY LIST(YEAR(adate))
o (
o PARTITION p1999 VALUES IN (1995, 1999, 2003) DATA DIRECTORY = '/var/appdata/95/data' INDEX DIRECTORY = '/var/appdata/95/idx',
o PARTITION p2000 VALUES IN (1996, 2000, 2004) DATA DIRECTORY = '/var/appdata/96/data' INDEX DIRECTORY = '/var/appdata/96/idx',
o PARTITION p2001 VALUES IN (1997, 2001, 2005) DATA DIRECTORY = '/var/appdata/97/data' INDEX DIRECTORY = '/var/appdata/97/idx',
o PARTITION p2000 VALUES IN (1998, 2002, 2006) DATA DIRECTORY = '/var/appdata/98/data' INDEX DIRECTORY = '/var/appdata/98/idx'
);
DATA DIRECTORYå’�INDEX DIRECTORY的操作方法与CREATE TABLE语句中的table_option子句的操作方法一样。此table_option子句用于位于MyISAM表管理程序下的各表ã€�
可以为每个分区指定一个数据目录和一个索引目录。如果不指定,则数据和索引被存储在默认的MySQL数据目录中ã€�
o MAX_ROWSå’�MIN_ROWS分别用于将被存储在分区中的行数目最大值和行数目最小值ã€�max_number_of_rowså’�min_number_of_rows的å€�必须为正整数。和具有同样名称的桌面选项一样,max_number_of_rowså’�min_number_of_rows只作为对服务器的“建议”值,并不是硬性限值ã€�
o 自选的TABLESPACE子句可以用于为分区指定一个桌面空间。仅用于MySQL Clusterã€�
o 自选的[STORAGE] ENGINE子句可以把本分区中表的类型改为指定的类型。表的类型可以是æœ�MySQL服务器支持的所有类型ã€�STORAGE关键字和等号(=)均为自选项。如果没有使用此选项设置分区存储引擎,则适用于整个表的引擎可以用于此分区ã€�
注释:分区管理程序对äº�PARTITIONå’�SUBPARTITION均接å��[STORAGE] ENGINE选项。目前,此子句的使用方式仅限于对所有的分区或子分区设置同一个存储引擎,如果试图在同一个表内对不同的分区或子分区设置不同的存储引擎,则会出现错è¯�ERROR 1469 (HY000):在本版本的MySQL中,不允许在各分区中混用管理程序。我们打算在将来çš�MySQL 5.1版本中加入这种对分区的限定ã€�
o NODEGROUP选项可以用于使本分区可以作为节点组的一部分,节点组使用node_group_id识别。本选项仅适用äº�MySQL Clusterã€�
o 分区定义可以自选地包含一个或多个subpartition_definition子句。每个这种子句至少包æ‹�SUBPARTITION name,此处,name是子分区的识别名称。除了用SUBPARTITION代替PARTITION关键词外,用于子分区定义的语法与用于分区定义的语法一样ã€�
子分区必须由HASHæˆ�KEY完成,并且只能对RANGEæˆ�LIST分区进行子分区。请参见18.2.5节,“子分区â€�ã€�
· 分区可以修改、合并、添加到表中,或从表中删去。要了解有关完成这些任务çš�MySQL命令的基本说明,请参è§�13.1.2节,“ALTER TABLE语法â€�。要了解详细的说明和示例,请参见18.3节,“分区管理â€�ã€�
您可以在CREATE TABLE语句的末尾添加一ä¸�SELECT语句,在一个表的基础上创建表ã€�
CREATE TABLE new_tbl SELECT * FROM orig_tbl;
MySQL会对SELECT中的所有项创建新列。举例说明:
mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
-> PRIMARY KEY (a), KEY(b))
-> TYPE=MyISAM SELECT b,c FROM test2;
本语句用于创建含三个列(a, b, c)的MyISAM表。注意,ç”�SELECT语句创建的列附在表的右侧,而不是覆盖在表上。参考以下示例:
mysql> SELECT * FROM foo;
+---+
| n |
+---+
| 1 |
+---+
mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM bar;
+------+---+
| m | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)
对应于表foo中的每一行,在表bar中插入一行,含有è¡�foo中的值以及新列中的默认值ã€�
在由CREATE TABLE...SELECT生成的表中,只在CREATE TABLE部分中命名的列首先出现。在两个部分中都命名的列和只åœ�SELECT部分中命名的列随后出现。也可以通过指定CREATE TABLE部分中的列覆ç›�SELECT列中的数据类型ã€�
如果在把数据复制到表中时出现错误,则表会自动被取消,不会被创建ã€�
CREATE TABLE...SELECT不会自动创建任何索引。索引需要专门创建,以便使语句的灵活性更强。如果您希望为已创建的表建立索引,您应在SELECT语句前指定索引ã€�
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
列的类型会发生部分转化。例如,AUTO_INCREAMENT属性不会被保留ï¼�VARCHAR列会变成CHAR列ã€�
当使ç”�CREATE...SELECT创建表时,在查询时一定要对功能调用和表达式起别名。如果不起别名,åˆ�CREATE语句会出现错误或者生成不符合需要的列名称ã€�
CREATE TABLE artists_and_works
SELECT artist.name, COUNT(work.artist_id) AS number_of_works
FROM artist LEFT JOIN work ON artist.id = work.artist_id
GROUP BY artist.id;
您也可以明确地为一个已生成的列指定类型ï¼�
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
根据其它表的定义(包括在原表中定义的所有的列属性和索引),使用LIKE创建一个空è¡�:
CREATE TABLE new_tbl LIKE orig_tbl;
CREATE TABLE...LIKE不会复制对原表或外键定义指定çš�DATA DIRECTORYæˆ�INDEX DIRECTORY表选项ã€�
您可以在SELECT前增åŠ�IGNOREæˆ�REPLACE,指示如何对复制唯一关键字值的记录进行操纵。使ç”�IGNORE后,如果新记录复制了原有的唯一关键字值的记录,则新记录被丢弃。使ç”�REPLACE后,新记录替换具有相同的唯一关键字值的记录。如果没有指å®�IGNOREæˆ�REPLACE,则出现多重唯一关键字值时会导致发生错误ã€�
为了确保更新日志/二进位日志可以被用于再次创建原表ï¼�MySQL不允许在CREATE TABLE...SELECT过程中进行联合插入ã€�
在有些情况下,较早版本的MySQL会静默地更改åœ�CREATE TABLEæˆ�ALTER TABLE语句中给定的列规约。在MySQL 5.1中不会进行这类变更。如果使用指定的数据类型无法创建列,则会出现错误ã€�
DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
DROP DATABASE用于取消数据库中的所用表格和取消数据库。使用此语句时要非常小心!如果要使用DROP DATABASE,您需要获得数据库DROP权限ã€�
IF EXISTS用于防止当数据库不存在时发生错误ã€�
也可以使ç”�DROP SCHEMAã€�
如果您对一个带有符号链接的数据库使ç”�DROP DATABASE,则链接和原数据库都被取消ã€�
DROP DATABASE会返回已被取消的表的数目。此数目相当于被取消çš�.frm文件的数目ã€�
在正常操作中MySQL自身会创建出一些文件和目录ã€�DROP DATABASE语句会从给定的数据库目录中取消这些文件和目录ï¼�
· 所有带这些扩展名的文件ï¼�
|
.BAK |
.DAT |
.HSH |
|
|
.MRG |
.MYD |
.ISD |
|
|
.MYI |
.db |
.frm |
|
· 名称中包含两ä½�16进制æ•�00-ff的所有子目录。这些子目录用于RAID表。(当对RAID表的支持被取消时,在MySQL 5.0中,这些目录不会被取消。您应该在升级到MySQL 5.0或更新的版本前转化原有的RAID表,并人工取消这些目录。请参见MySQL 5.0参考手册中有关从较早版本升级到MySQL 5.0的章节ã€�MySQL 5.0参考手册可以从MySQL网站中获取。)
· db.opt文件
如果åœ�MySQL取消了上述这些文件之后,在数据库目录中仍保留有其它文件和目录,则数据库目录不能被取消。在这种情况下,您必须人工取消所有保留下的文件或目录,并再次发é€�DROP DATABASE语句ã€�
您还可以使用mysqladmin来取消文件。请参见8.5节,“mysqladmin:用于管理MySQL服务器的客户端â€�ã€�
DROP INDEX index_name ON tbl_name
DROP INDEX用于从表tbl_name中取消名称为index_name的索引。本语句被映射到一ä¸�ALTER TABLE语句中,用于取消索引。请参见13.1.2节,“ALTER TABLE语法â€�ã€�
DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name [, tbl_name] ...
[RESTRICT | CASCADE]
DROP TABLE用于取消一个或多个表。您必须有每个表çš�DROP权限。所有的表数据和表定义会被取消,所以使用本语句要小心!
注意,对于一个带分区的表ï¼�DROP TABLE会永久性地取消表定义,取消各分区,并取消储存在这些分区中的所有数据ã€�DROP TABLE还会取消与被取消的表有关联的分区定义ï¼�.par)文件ã€�
对与不存在的表,使用IF EXISTS用于防止错误发生。当使用IF EXISTS时,对于每个不存在的表,会生成一ä¸�NOTE。请参见13.5.4.22节,“SHOW WARNINGS语法â€�ã€�
RESTRICTå’�CASCADE可以使分区更容易。目前,RESTRICTå’�CASCADE不起作用ã€�
注释:除非您使用TEMPORARY关键词,DROP TABLE会自动提交当前的有效的事务ã€�
TEMPORARY关键词具有以下作用:
· 语句只取æ¶�TEMPORARY表ã€�
· 语句不会终止正在进行中的事务ã€�
· 不会查验存取权。(TEMPORARY表仅对于创建该表的客户端是可见的,所以查验是不必要的。)
使用TEMPORARY是确保您不会意外取消一个非TEMPORARY表的良好方法ã€�
RENAME TABLE tbl_name TO new_tbl_name
[, tbl_name2 TO new_tbl_name2] ...
本语句用于对一个或多个表进行重命名ã€�
重命名操作自动进行,这意味着当重命名正在运行时,其它线程不能读取任何表。例如,如果您有一个原有的è¡�old_table,您可以创建另一个具有相同结构的空表new_table,然后用此空表替换原有的表:
CREATE TABLE new_table (...);
RENAME TABLE old_table TO backup_table, new_table TO old_table;
如果此语句用于对多个表进行重命名,则重命名操作从左至右进行。如果您想要交换两个表的名称,您可以这样做(假设不存在名称为tmp_table的表):
RENAME TABLE old_table TO tmp_table,
new_table TO old_table,
tmp_table TO new_table;
只要两个数据库位于同一文件系统中,您还可以对表进行重命名,把表从一个数据库中移动到另一个数据库中:
RENAME TABLE current_db.tbl_name TO other_db.tbl_name;
当您执行RENAME时,您不能有被锁定的表,也不能有处于活性状态的事务。您还必须拥有原表的ALTERå’�DROP权限,以及新表的CREATEå’�INSERT权限ã€�
如果MySQL对多个表进行重命名时遇到了错误,MySQL会对所有已被重命名的表进行反向重命名,返回到原来的状态ã€�
只要您不尝试通过重命名把视图加入另一个数据库中,åˆ�RENAME TABLE也可以用于视图ã€�
单表语法ï¼�
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]
多表语法ï¼�
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
tbl_name[.*] [, tbl_name[.*] ...]
FROM table_references
[WHERE where_definition]
或:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM tbl_name[.*] [, tbl_name[.*] ...]
USING table_references
[WHERE where_definition]
tbl_name中有些行满足ç”�where_definition给定的条件ã€�DELETE用于删除这些行,并返回被删除的记录的数目ã€�
如果您编写的DELETE语句中没æœ�WHERE子句,则所有的行都被删除。当您不想知道被删除的行的数目时,有一个更快的方法,即使用TRUNCATE TABLE。请参见13.2.9节,“TRUNCATE语法â€�ã€�
如果您删除的行中包括用于AUTO_INCREMENT列的最大值,则该值被重新用于BDB表,但是不会被用äº�MyISAM表或InnoDB表。如果您åœ�AUTOCOMMIT模式下使ç”�DELETE FROM tbl_name(不å��WHERE子句)删除表中的所有行,则对于所有的表类型(é™�InnoDBå’�MyISAM外),序列重新编排。对äº�InnoDB表,此项操作有一些例外,åœ�15.2.6.3节,“AUTO_INCREMENT列如何在InnoDB中运行â€�中进行了讨论ã€�
对于MyISAMå’�BDB表,您可以把AUTO_INCREMENT次级列指定到一个多列关键字中。在这种情况下,从序列的顶端被删除的值被再次使用,甚至对äº�MyISAM表也如此。请参见3.6.9节,“使用AUTO_INCREMENTâ€�ã€�
DELETE语句支持以下修饰符:
· 如果您指å®�LOW_PRIORITY,则DELETE的执行被延迟,直到没有其它客户端读取本表时再执行ã€�
· 对于MyISAM表,如果您使ç”�QUICK关键词,则在删除过程中,存储引擎不会合并索引端结点,这样可以加快部分种类的删除操作的速度ã€�
· 在删除行的过程中ï¼�IGNORE关键词会ä½�MySQL忽略所有的错误。(在分析阶段遇到的错误会以常规方式处理。)由于使用本选项而被忽略的错误会作为警告返回ã€�
删除操作的速度会受到一些因素的影响,这些因素在7.2.18节,“DELETE语句的速度â€�中进行了讨论ã€�
åœ�MyISAM表中,被删除的记录被保留在一个带链接的清单中,后续的INSERT操作会重新使用旧的记录位置。要重新使用未使用的空间并减小文件的尺寸,则使用OPTIMIZE TABLE语句æˆ�myisamchk应用程序重新编排表ã€�OPTIMIZE TABLE更简便,但是myisamchk速度更快。请参见13.5.2.5节,“OPTIMIZE TABLE语法â€�å’�ç¬�7章:优化ã€�
QUICK修饰符会影响到在删除操作中索引端结点是否合并。当用于被删除的行的索引值被来自后插入的行的相近的索引值代替时ï¼�DELETE QUICK最为适用。在此情况下,被删除的值留下来的空穴被重新使用ã€�
未充满的索引块跨越某一个范围的索引值,会再次发生新的插入。当被删除的值导致出现未充满的索引块时,DELETE QUICK没有作用。在此情况下,使ç”�QUICK会导致未利用的索引中出现废弃空间。下面是此种情况的举例说明:
1. 创建一个表,表中包含已编索引的AUTO_INCREMENT列ã€�
2. 在表中插入很多记录。每次插入会产生一个索引值,此索引值被添加到索引的高端处ã€�
3. 使用DELETE QUICK从列的低端处删除一组记录ã€�
在此情况下,与被删除的索引值相关的索引块变成未充满的状态,但是,由于使用了QUICK,这些索引块不会与其它索引块合并。当插入新值时,这些索引块仍为未充满的状态,原因是新记录不含有在被删除的范围内的索引值。另外,即使您此后使ç”�DELETE时不包含QUICK,这些索引块也仍是未充满的,除非被删除的索引值中有一部分碰巧位于这些未充满的块的之中,或与这些块相邻。在这些情况下,如果要重新利用未使用的索引空间,需使用OPTIMIZE TABLEã€�
如果您打算从一个表中删除许多行,使ç”�DELETE QUICK再加ä¸�OPTIMIZE TABLE可以加快速度。这样做可以重新建立索引,而不是进行大量的索引块合并操作ã€�
用于DELETEçš�MySQL唯一çš�LIMIT row_count选项用于告知服务器在控制命令被返回到客户端前被删除的行的最大值。本选项用于确保一ä¸�DELETE语句不会占用过多的时间。您可以只重å¤�DELETE语句,直到相关行的数目少äº�LIMIT值为歀€�
如果DELETE语句包括一ä¸�ORDER BY子句,则各行按照子句中指定的顺序进行删除。此子句只在ä¸�LIMIT联用是才起作用。例如,以下子句用于查找ä¸�WHERE子句对应的行,使ç”�timestamp_column进行分类,并删除第一(最旧的)行ï¼�
DELETE FROM somelog
WHERE user = 'jcole'
ORDER BY timestamp_column
LIMIT 1;
您可以在一ä¸�DELETE语句中指定多个表,根据多个表中的特定条件,从一个表或多个表中删除行。不过,您不能在一个多è¡�DELETE语句中使ç”�ORDER BYæˆ�LIMITã€�
table_references部分列出了包含在联合中的表。此语法åœ�13.2.7.1节,“JOIN语法â€�中进行了说明ã€�
对于第一个语法,只删除列äº�FROM子句之前的表中的对应的行。对于第二个语法,只删除列于FROM子句之中(在USING子句之前)的表中的对应的行。作用是,您可以同时删除许多个表中的行,并使用其它的表进行搜索:
DELETE t1, t2 FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;
或:
DELETE FROM t1, t2 USING t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;
当搜索待删除的行时,这些语句使用所有三个表,但是只从表t1和表t2中删除对应的行ã€�
以上例子显示了使用逗号操作符的内部联合,但是多è¡�DELETE语句可以使用SELECT语句中允许的所有类型的联合,比å¦�LEFT JOINã€�
本语法允许在名称后面åŠ�.*,以便与Access相容ã€�
如果您使用的多表DELETE语句包括InnoDB表,并且这些表受外键的限制,åˆ�MySQL优化程序会对表进行处理,改变原来的从属关系。在这种情况下,该语句出现错误并返回到前面的步骤。要避免此错误,您应该从单一表中删除,并依靠InnoDB提供çš�ON DELETE功能,对其它表进行相应的修改ã€�
注释:当引用表名称时,您必须使用别名(如果已给定):
DELETE t1 FROM test AS t1, test2 WHERE ...
进行多表删除时支持跨数据库删除,但是在此情况下,您在引用表时不能使用别名。举例说明:
DELETE test1.tmp1, test2.tmp2 FROM test1.tmp1, test2.tmp2 WHERE ...
目前,您不能从一个表中删除,同时又在子查询中从同一个表中选择ã€�
HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE
HANDLER语句提供通往表存储引擎接口的直接通道ã€�HANDLER可以用于MyISAMå’�InnoDB表ã€�
HANDLER...OPEN语句用于打开一个表,通过后续çš�HANDLER...READ语句建立读取表的通道。本表目标不会被其它线程共享,也不会关闭,直到线程调ç”�HANDLER...CLOSE或线程中止时为止。如果您使用一个别名打开表,则使用其å®�HANDLER语句进一步参阅表是必须使用此别名,而不能使用表名ã€�
如果被指定的索引满足给定的值并且符合了WHERE条件,则第一ä¸�HANDLER...READ语法取出一行。如果您有一个多列索引,则指定索引列值为一个用逗号隔开的清单。既可以为索引中的所有列指定值,也可以为索引列的最左边的前缀指定值。假设一个索引包括三个列,名称为col_a, col_b,å’�col_c,并按此顺序排列ã€�HANDLER语句可以为索引中的所有三个列指定值,或者为一个最左边前缀中的各列指定值。举例说明:
HANDLER ... index_name = (col_a_val,col_b_val,col_c_val) ...
HANDLER ... index_name = (col_a_val,col_b_val) ...
HANDLER ... index_name = (col_a_val) ...
第二ä¸�HANDLER...READ语法按索引的顺序从表中取出一行。索引的顺序符合WHERE条件ã€�
第三ä¸�HANDLER...READ语法按自然行的顺序从表中取出一行。自然行的顺序符å��WHERE条件。当想要对整个表进行扫描时,此语句比HANDLER tbl_name READ index_name更快。自然行的顺序指的是行存储在MyISAM表数据文件的顺序。本语句也适用äº�InnoDB表,但是因为没有独立的数据文件,所以没有这类概念ã€�
不使ç”�LIMIT子句时,所有形式的HANDLER...READ语句均只取出一行ã€� 如果要返回多个行,应加入一ä¸�LIMIT子句。本语句äº�SELECT语句的语法一样。请参见13.2.7节,“SELECT语法â€�ã€�
HANDLER...CLOSE用于关闭使用HANDLER...OPEN打开的表ã€�
注释:要使用HANDLER接口来查阅一个表çš�PRIMARY KEY,应使用带引号的识别ç¬�`PRIMARY`ï¼�
HANDLER tbl_name READ `PRIMARY` > (...);
HANDLER是比较低级别的语句。例如,它不能提供一致性。也就是说,HANDLER...OPEN不能为表做快照,也不能锁定表。这意味着,当一ä¸�HANDLER...OPEN语句被编写后,表数据可以被更改(用此线程或用其它线程),并且这些更改只会部分地出现在HANDLER...NEXTæˆ�HANDLER...PREV扫描中ã€�
使用HANDLER接口代替常规çš�SELECT语句有多个原因:
· HANDLERæ¯�SELECT更快ï¼�
o 一个指定的存储引擎管理程序目标为了HANDLER...OPEN进行整序。该目标被重新用于该表的后续çš�HANDLER语句;不需要对每个语句进行重新初始化ã€�
o 涉及的分析较少ã€�
o 没有优化程序或查询校验开销ã€�
o 在两个管理程序请求之间,不需要锁定表ã€�
o 管理程序接口不需要提供外观一致的数据(例如,允许无条理的读取),所以存储引擎可以使用优化,è€�SELECT通常不允许使用优化ã€�
· 有些应用程序使用ä¸�ISAM近似的接口与MySQL连接。使ç”�HANDLER可以更容易地与这些应用程序连接ã€�
· HANDLER允许您采用一种特殊的方式进出数据库。而使ç”�SELECT时难以采用(或不可能采用)这种方式。有些应用程序可以提供一个交互式的用户接口与数据库连接。当与这些应用程序同时使用时,用HANDLER接口观看数据更加自然ã€�
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
VALUES ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
或:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
或:
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
INSERT用于向一个已有的表中插入新行ã€�INSERT...VALUESå’�INSERT...SET形式的语句根据明确指定的值插入行ã€�INSERT...SELECT形式的语句插入从其它表中选出的行。在13.2.4.1节,“INSERT ... SELECT语法â€�中对INSERT...SELECT进行了进一步的讨论ã€�
行应被插入到tbl_name表中。可以按以下方法指定列。本语句向这些列提供值ã€�
· 列名称清单或SET子句明确的指示了列ã€�
· 如果您不ä¸�INSERT...VALUESæˆ�INSERT...SELECT指定列的清单,则表中每列的值必须在VALUES清单中提供,或由SELECT提供。如果您不知道表中各列的顺序,则使用DESCRIBE tbl_name查询ã€�
列值可以采用多种方法给定:
· 如果不是在严格模式下运行,则所有没有明确给定值的列都被设置为默认值(明确的或隐含的)。例如,如果您指定了一个列清单,但此清单没有对表中所有的列进行命名,则未命名的各列被设置为默认值。默认值的赋值在13.1.5节,“CREATE TABLE语法â€�中进行了说明。也可参è§�1.8.6.2节,“对无效数据的约束â€�ã€�
有时候,您需要对所有没有默认值的列明确地指定值。如果您希望,在没有明确指定值时ï¼�INSERT语句可以生成错误信息,则您应该使ç”�STRICT模式。请参见5.3.2节,“SQL服务器模式â€�ã€�
· 使用关键è¯�DEFAULT,明确地把列设置为默认值。这样,编写向所有列赋值的INSERT语句时可以更容易,因为使ç”�DEFAULT可以避免编写出不完整的、未包含全部列值的VALUES清单。如果不使用DEFUALT,您必须编写一个列名称清单,与VALUES清单中的每个值对应ã€�
您还可以使用DEFAULT(col_name)作为一种更通用的形式,在表达式中使用,用于生成一个列的默认值ã€�
· 如果列清单和VALUES清单均为空清单,åˆ�INSERT会创建一个行,每个列都被设置为默认值:
· mysql> INSERT INTO tbl_name () VALUES();
åœ�STRICT模式中,如果有一列没有默认值,则会出现错误。或者,MySQL会对所有没有明确定义默认值的列使用隐含的默认值ã€�
· 您可以指定一个表达式expr来提供一个列值。如果表达式的类型与列值不匹配,这样做会造成类型转化。并且,给定值的转化会导致不同的插入值,插入何值由列类型而定。例如,向一ä¸�INT, FLOAT, DECIMAL(10,6)æˆ�YEAR列插入字符串'1999.0e-2',插入值分别是1999ï¼�19.9921ï¼�19.992100å’�1999。存储在INTå’�YEAR列中的值为1999的原因是,在从字符串到整数的转化中,只把字符串的前面部分看作有效的整数或年份。对于浮点列和固定点列,在从字符串到浮点的转化中,把整个字符串均看作有效的浮点值ã€�
表达å¼�expr可以引用在值清单中已设置的所有列。例如,您可以这么操作,因为用于col2的值引用了col1,è€�col1已经被赋值:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
但是以下语句不合法,因为用于col1的值引用了col2,è€�col2åœ�col1之后被赋值:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
有一种例外情况,那就是含æœ�AUTO_INCREMENT值的列。因ä¸�AUTO_INCREMENT值在其它值赋值之后被生成,所以任何在赋值时å¯�AUTO_INCREMENT列的引用都会返回0ã€�
INSERT语句支持下列修改符:
· 如果您使ç”�DELAYED关键字,则服务器会把待插入的行放到一个缓冲器中,而发é€�INSERT DELAYED语句的客户端会继续运行。如果表正在被使用,则服务器会保留这些行。当表空闲时,服务器开始插入行,并定期检查是否有新的读取请求。如果有新的读取请求,则被延迟的行被延缓执行,直到表再次空闲时为歀€‚请参见13.2.4.2节,“INSERT DELAYED语法â€�ã€�
· 如果您使ç”�LOW_PRIORITY关键词,åˆ�INSERT的执行被延迟,直到没有其它客户端从表中读取为歀€‚当原有客户端正在读取时,有些客户端刚开始读取。这些客户端也被包括在内。此时,INSERT LOW_PRIORITY语句等候。因此,在读取量很大的情况下,发å‡�INSERT LOW_PRIORITY语句的客户端有可能需要等待很长一段时间(甚至是永远等待下去)。(这与INSERT DELAYED形成对比ï¼�INSERT DELAYED立刻让客户端继续执行。请参见13.2.4.2节,“INSERT DELAYED语法â€�。)注意LOW_PRIORITY通常不应用于MyISAM表,因为这么做会取消同时进行的插入。请参见15.1节,“MyISAM存储引擎â€�ã€�
· 如果您指定了HIGH_PRIORITY,同时服务器采用--low-priority-updates选项启动,则HIGH_PRIORITY将覆ç›�--low-priority-updates选项。这么做还会导致同时进行的插入被取消ã€�
· 使用mysql_affected_rows() C API函数,可以获得用äº�INSERT的受影响行的值。请参见25.2.3.1节,“mysql_affected_rows()â€�ã€�
· 如果您在一ä¸�INSERT语句中使ç”�IGNORE关键词,在执行语句时出现的错误被当作警告处理。例如,没有使用IGNORE时,如果一个行复制了原有的UNIQUE索引æˆ�PRIMARY KEY值,会导致出现重复关键字错误,语句执行失败。使ç”�IGNORE时,该行仍然未被插入,但是不会出现错误ã€�IGNORE未被指定时,如果数据转化引发错误,则会使语句执行失败。使ç”�IGNORE后,无效数据被调整到最接近的值,并被插入;此时,生成警告,但是语句执行不会失败。您可以使用mysql_info() C API函数测定有多少行被插入到表中ã€�
如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一ä¸�UNIQUE索引æˆ�PRIMARY KEY中出现重复值,则执行旧è¡�UPDATE。例如,如果åˆ�a被定义为UNIQUE,并且包含å€�1,则以下两个语句具有相同的效果:
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
-> ON DUPLICATE KEY UPDATE c=c+1;
mysql> UPDATE table SET c=c+1 WHERE a=1;
如果行作为新记录被插入,则受影响行的值为1;如果原有的记录被更新,则受影响行的值为2ã€�
注释:如果列b也是唯一列,åˆ�INSERT与此UPDATE语句相当ï¼�
mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
如果a=1 OR b=2与多个行向匹配,则只有一个行被更新。通常,您应该尽量避免对带有多个唯一关键字的表使ç”�ON DUPLICATE KEY子句ã€�
您可以在UPDATE子句中使ç”�VALUES(col_name)函数ä»�INSERT...UPDATE语句çš�INSERT部分引用列值。换句话说,如果没有发生重复关键字冲突,åˆ�UPDATE子句中的VALUES(col_name)可以引用被插入的col_name的值。本函数特别适用于多行插入ã€�VALUES()函数只在INSERT...UPDATE语句中有意义,其它时候会返回NULLã€�
示例ï¼�
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
-> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
本语句与以下两个语句作用相同ï¼�
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
-> ON DUPLICATE KEY UPDATE c=3;
mysql> INSERT INTO table (a,b,c) VALUES (4,5,6)
-> ON DUPLICATE KEY UPDATE c=9;
当您使用ON DUPLICATE KEY UPDATE时,DELAYED选项被忽略ã€�
您可以使ç”�SQL LAST_INSERT_ID()函数查找用于AUTO_INCREMENT列的值。从C API的内部,使用mysql_insert_id()函数。不过,您应该注意,两个函数的作用并不总是相同的。在12.9.3节,“信息函数â€�å’�25.2.3.36节,“mysql_insert_id()â€�中进一步讨论了ä¸�AUTO_INCREMENT列有关的INSERT语句的作用ã€�
如果您使ç”�INSERT...VALUES语句时采用了多个值清单或INSERT...SELECT,则该语句按以下格式返回一个信息字符串ï¼�
Records: 100 Duplicates: 0 Warnings: 0
记录指示了经过语句处理的行的数目。(因为重复数目可以不是零,所以该数目不一定是实际被插入的行的数目。)重复数目指的是不能被插入的行的数目,因为这些行会复制部分原有的唯一索引值。警告指的是插入有错误或有问题的列值的次数。在以下情况下会出现警告ï¼�
· 向一个已定义ä¸�NOT NULL的列中插å…�NULL。对于一个多è¡�INSERT语句æˆ�INSERT INTO...SELECT语句,根据列数据的类型,列被设置为隐含的默认值。对于数字类型,默认值为0;对于字符串类型,默认值为空字符串('');对于日期和时间类型,默认值为â€�zero”值。对INSERT INTO...SELECT语句的处理方法与对多行插入的处理方法一样,因为服务器不能检测来è‡�SELECT的结果,不能判断是否返回单一行。(对于单一è¡�INSERT,当NULL被插入一ä¸�NOT NULL列时,不会出现警告,而是出现错误,并且语句运行失败。)
· 数字列的值被设置在列的值范围之外。此值被修改为未最接近的值范围端点ã€�
· 向一个数字列赋予一个例å¦�'10.34 a'的值。尾部的非数字文本被删节,其余的数字部分被插入,如果字符串值没有前导的数字部分,则该列被设置为0ã€�
· 向一个字符串列(CHAR, VARCHAR, TEXTæˆ�BLOB)中插入的字符串超过了列的最大长度。此值被删节到列的最大长度ã€�
· 向日期或时间列中插入的值对于该列的类型是不合法的。根据列的类型,该列被设置到相应的零值ã€�
如果您正在使ç”�C API,则可以通过调用mysql_info()函数获取信息字符串。请参见25.2.3.34节,“mysql_info()â€�ã€�
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
使用INSERT...SELECT,您可以快速地从一个或多个表中向一个表中插入多个行ã€�
示例ï¼�
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
使用INSERT...SELECT语句时会出现以下情况ï¼�
· 明确地指å®�IGNORE,用于忽略会导致重复关键字错误的记录ã€�
· 不要同时使用DELAYEDå’�INSERT...SELECTã€�
· INSERT语句的目标表会显示在查询çš�SELECT部分çš�FROM子句中。(在有些旧版本çš�MySQL中不会出现这种情况。)
· AUTO_INCREMENT列照常运行ã€�
· 为了确保二进制日志可以被用于再次创建原表ï¼�MySQL不允许在INSERT...SELECT运行期间同时进行插入操作ã€�
· 目前,您不能在向一个表插入的同时,又在一个子查询中从同一个表中选择ã€�
åœ�ON DUPLICATE KEY UPDATE的值部分中,只要您不使ç”�SELECT部分中的GROUP BY,您就可以引用在其它表中的列。有一个副作用是,您必须使值部分中的非唯一列的名称符合要求ã€�
您可以使ç”�REPLACE替代INSERT,来覆盖旧行。对于包含唯一关键字值,并复制了旧行的新行,在进行处理时ï¼�REPLACE可以作为INSERT IGNORE的同类子句:新行被用于替换旧行,而不是被丢弃ã€�
INSERT DELAYED ...
用于INSERT语句çš�DELAYED选项æ˜�MySQL相对于标å‡�SQL的扩展。如果您的客户端不能等待INSERT完成,则这个选项是非常有用的。当您使ç”�MySQL进行日志编写时,这是非常常见的问题。您也可以定期运è¡�SELECTå’�UPDATE语句,这些语句花费的时间较长ã€�
当一个客户端使用INSERT DELAYED时,会立刻从服务器处得到一个确定。并且行被排入队列,当表没有被其它线程使用时,此行被插入ã€�
使用INSERT DELAYED的另一个重要的好处是,来自许多客户端的插入被集中在一起,并被编写入一个块。这比执行许多独立的插入要快很多ã€�
使用DELAYED时有一些限制:
· INSERT DELAYED仅适用äº�MyISAM, MEMORYå’�ARCHIVE表。对äº�MyISAM表,如果在数据文件的中间没有空闲的块,则支持同时采用SELECTå’�INSERT语句。在这些情况下,基本不需要对MyISAM使用INSERT DELAYED。请参见15.1节,“MyISAM存储引擎â€�, 15.4节,“MEMORY (HEAP)存储引擎â€�å’�15.8节,“ARCHIVE存储引擎â€�ã€�
· INSERT DELAYED应该仅用于指定值清单的INSERT语句。服务器忽略用于INSERT DELAYED...SELECT语句çš�DELAYEDã€�
· 服务器忽略用äº�INSERT DELAYED...ON DUPLICATE UPDATE语句çš�DELAYEDã€�
· 因为在行被插入前,语句立刻返回,所以您不能使用LAST_INSERT_ID()来获å��AUTO_INCREMENT值ã€�AUTO_INCREMENT值可能由语句生成ã€�
· 对于SELECT语句ï¼�DELAYED行不可见,直到这些行确实被插入了为止ã€�
· DELAYED在从属复制服务器中被忽略了,因为DELAYED不会在从属服务器中产生与主服务器不一样的数据ã€�
注意,目前在队列中的各行只保存在存储器中,直到它们被插入到表中为歀€‚这意味着,如果您强行中止äº�mysqld(例如,使用kill -9)或者如æž�mysqld意外停止,则所有没有被写入磁盘的行都会丢失ã€�
以下详细描述了当您对INSERTæˆ�REPLACE使用DELAYED选项时会发生什么情况。在这些描述中,“线程”指的是已接受了一ä¸�INSERT DELAYED语句的线程,“管理程序”指的是为某个特定的表处理所æœ�INSERT DELAYED语句的线程ã€�
· 当一个线程对一个表执行DELAYED语句时,会创建出一个管理程序线程(如果原来不存在),对用于本表的所æœ�DELAYED语句进行处理ã€�
· 线程会检查是否管理程序以前已获取äº�DELAYED锁定;如果没有获取,则告知管理程序线程进行此项操作。即使其它线程对表有READæˆ�WRITE锁定,也可以获得DELAYED锁定。但是管理程序会等待所有的ALTER TABLE锁定æˆ�FLUSH TABLE锁定,以确保表的结构是最新的ã€�
· 线程执行INSERT语句,但不是把行写入表中,而是把最终行的拷贝放入一个由管理程序线程管理的队列中。线程会提示出现语法错误,这些错误会被报告到客户端中ã€�
· 因为在插入操作之前,INSERT返回已经完成,所以客户端不能从服务器处获取重复记录的数目,也不能获取生成的行çš�AUTO_INCREMENT值。(如果您使ç”�C API,则出于同样的原因,mysql_info()函数不会返回任何有意义的东西。)
· 当行被插入表中时,二进制日志被管理程序线程更新。在多行插入情况下,当第一行被插入时,二进制日志被更新ã€�
· 每次delayed_insert_limit行被编写时,管理程序会检查是否有SELECT语句仍然未执行。如果有,则会在继续运行前,让这些语句先执行ã€�
· 当管理程序的队列中没有多余的行时,表被解锁。如果在delayed_insert_timeout时间内,没有接收到新çš�INSERT DELAYED语句,则管理程序中止ã€�
· 如果在某个特定的管理程序队列中,有超è¿�delayed_queue_size的行未被执行,则申请INSERT DELAYED的线程会等待,直到队列中出现空间为止。这么做可以确保mysqld不会把所有的存储器都用于被延迟的存储队列ã€�
· 管理程序线程会显示在MySQL进程清单中,其命令列中包å��delayed_insert。如果您执行一ä¸�FLUSH TABLES语句或使ç”�KILL thread_id进行删除,则会删除此线程。不过,在退出前,线程会首先把所有排入队列的行存储到表中。在这期间,该线程不会从其它线程处接受任何新çš�INSERT语句。如果您在此之后执行一ä¸�INSERT DELAYED语句,则会创建出一个新的管理程序线程ã€�
注意,如果有一ä¸�INSERT DELAYED管理程序正在运行,则这意味着INSERT DELAYED语句比常规的INSERT语句具有更高的优先权。其它更新语句必须等待,直到INSERT DELAYED语句队列都运行完毕,或者管理程序线程被中止(使ç”�KILL thread_id),或者执行了一ä¸�FLUSH TABLES时为歀€�
· 以下状态变量提供了有关INSERT DELAYED语句的信息:
|
状态变é‡� |
意义 |
|
Delayed_insert_threads |
管理程序线程的数ç›� |
|
Delayed_writes |
使用INSERT DELAYED写入的行的数ç›� |
|
Not_flushed_delayed_rows |
等待被写入的行的数目 |
· 您可以通过发送一ä¸�SHOW STATUS语句,或者执行一ä¸�mysqladmin extended-status命令,来阅览这些变量ã€�
注意,当没有使用表时ï¼�INSERT DELAYED比常规的INSERT要慢。对于服务器来说,为每个含有延迟行的表操纵一个独立的线程,也是一个额外的系统开销。这意味着只有当您确认您需要时,才应使ç”�INSERT DELAYEDã€�
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[FIELDS
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char' ]
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number LINES]
[(col_name_or_user_var,...)]
[SET col_name = expr,...)]
LOAD DATA INFILE语句用于高速地从一个文本文件中读取行,并装入一个表中。文件名称必须为一个文字字符串ã€�
要了解有å…�INSERTå’�LOAD DATA INFILE的效率的对比和有å…�LOAD DATA INFILE加速的更多信息,请参见7.2.16节,“INSERT语句的速度â€�ã€�
ç”�character_set_database系统变量指示的字符集被用于解释文件中的信息ã€�SET NAMESå’�character_set_client的设置不会影响对输入的解释ã€�
注意,目前不能载å…�UCS2数据文件ã€�
您也可以通过使用mysqlimport应用程序载入数据文件;通过向服务器发送一ä¸�LOAD DATA INFILE语句实现此功能ã€�--local选项用于ä½�mysqlimport从客户主机中读取数据文件。如果客户端和服务器支持压缩协议,则您可以指定â€�compress选项提高在慢速网络中的性能。请参见8.10节,“mysqlimport:数据导入程åº�ã€�
如果您使ç”�LOW_PRIORITY,则LOAD DATA语句的执行被延迟,直到没有其它的客户端从表中读取为止ã€�
如果一ä¸�MyISAM表满足同时插入的条件(即该表在中间有空闲块),并且您对这ä¸�MyISAM表指定了CONCURRENT,则å½�LOAD DATA正在执行时,其它线程会从表中重新获取数据。即使没有其它线程在同时使用本表格,使用本选项也会略微影响LOAD DATA的性能ã€�
如果指定äº�LOCAL,则被认为与连接的客户端有关ï¼�
· 如果指定äº�LOCAL,则文件会被客户主机上的客户端读取,并被发送到服务器。文件会被给予一个完整的路径名称,以指定确切的位置。如果给定的是一个相对的路径名称,则此名称会被理解为相对于启动客户端时所在的目录ã€�
· 如果LOCAL没有被指定,则文件必须位于服务器主机上,并且被服务器直接读取ã€�
当在服务器主机上为文件定位时,服务器使用以下规则ï¼�
· 如果给定了一个绝对的路径名称,则服务器使用此路径名称ã€�
· 如果给定了带有一个或多个引导组件的相对路径名称,则服务器会搜索相对于服务器数据目录的文件ã€�
· 如果给定了一个不带引导组件的文件名称,则服务器会在默认数据库的数据库目录中寻找文件ã€�
注意,这些规则意味着名为./myfile.txt的文件会从服务器数据目录中被读取,而名ä¸�myfile.txt的同样的文件会从默认数据库的数据库目录中读取。例如,下面çš�LOAD DATA语句会从db1数据库目录中读取文件data.txt,因ä¸�db1是当前数据库。即使语句明确把文件载入åˆ�db2数据库中的表里,也会ä»�db1目录中读取ã€�
mysql> USE db1;
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
注意,使用正斜杠指定Windows路径名称,而不是使用反斜杠。如果您使用反斜杠,您必须使用两个ã€�
出于安全原因,当读取位于服务器中的文本文件时,文件必须位于数据库目录中,或者是全体可读的。另外,要对服务器文件使ç”�LOAD DATA INFILE,您必须拥有FILE权限ã€�
è§�5.7.3节,“MySQL提供的权限â€�ã€�
与让服务器直接读取文件相比,使用LOCAL速度略慢,这是因为文件的内容必须通过客户端发送到服务器上。不过,您不需è¦�FILE权限来载入本地文件ã€�
只有当您的服务器和您的客户端都许可时ï¼�LOCAL才可运行。例如,如果使用â€�local-infile=0启动mysqld,则LOCAL不运行。请参见5.6.4节,“LOAD DATA LOCAL安全问题â€�ã€�
如果您需è¦�LOAD DATA来从一个管道中读取,您可以使用以下方法(此处我们把/目录清单载入一个表格)ï¼�
mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
find / -ls > /mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x
有些输入记录把原有的记录复制到唯一关键字值上ã€�REPLACEå’�IGNORE关键字用于控制这些输入记录的操作ã€�
如果您指定了REPLACE,则输入行会替换原有行(换句话说,与原有行一样,对一个主索引或唯一索引具有相同值的行)。请参见13.2.6节,“REPLACE语法â€�ã€�
如果您指å®�IGNORE,则把原有行复制到唯一关键字值的输入行被跳过。如果您这两个选项都不指定,则运行情况根据LOCAL关键词是否被指定而定。不使用LOCAL时,当出现重复关键字值时,会发生错误,并且剩下的文本文件被忽略。使ç”�LOCAL时,默认的运行情况和IGNORE被指定时的情况相同;这是因为在运行中间,服务器没有办法中止文件的传输ã€�
如果您希望在载入运行过程中忽略外键的限制,您可以在执è¡�LOAD DATA前发送一ä¸�SET FOREIGN_KEY_CHECKS=0语句ã€�
如果您对一个空çš�MyISAM表使ç”�LOAD DATA INFILE,则所有的非唯一索引会被创建在一个独立批中(对于REPAIR TABLE)。当您有许多索引时,这通常会使LOAD DATA INFILE大大加快。通常ï¼�LOAD DATA INFILE的速度会非常快,但是在某些极端情况下,您可以在把文件载入到表中之前使用ALTER TABLE...DISABLE KEYS关闭LOAD DATA INFILE,或者在载入文件之后使用ALTER TABLE...ENABLE KEYS再次创建索引,使创建索引的速度更快。请参见7.2.16节,“INSERT语句的速度â€�ã€�
LOAD DATA INFILEæ˜�SELECT...INTO OUTFILE的补语。(è§�13.2.7节,“SELECT语法â€�。)要从一个表中把数据写入一个文件中,应使用SELECT...INTO OUTFILE。要读取文件,放回到表中,应使用LOAD DATA INFILEã€�FIELDSå’�LINES子句的语法对于两个语句是一样的。两个子句都是自选的,但是如果两个都被指定了ï¼�FIELDS必须位于LINES的前靀€�
如果您指定了一ä¸�FIELDS子句,则每个亚子句(TERMINATED BY, [OPTIONALLY] ENCLOSED BYå’�ESCAPED BY)也是自选的。不过,您必须指定其中至少一个ã€�
如果您不指定FIELDS子句,则默认值为假设您写下如下语句时的值:
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
如果您不指定LINES子句,则默认值为假设您写下如下语句时的值:
LINES TERMINATED BY '\n' STARTING BY ''
换句话说,当读取输入值时,默认值会ä½�LOAD DATA INFILE按如下方式运行:
· 在新行处寻找行的边界ã€�
· 不会跳过任何行前缀ã€�
· 在制表符处把行分解为字段ã€�
· 不希望字段被包含在任何引号字符之中ã€�
· 出现制表符、新行、或在â€�\’前有â€�\’时,理解为作为字段值一部分的文字字符ã€�
相反的,当编写输出值时,默认值会ä½�SELECT...INTO OUTFILE按如下方式运行:
· 在字段之间写入制表符ã€�
· 不把字段包含在任何引号字符中ã€�
· 当字段值中出现制表符、新行或â€�\’时,使用â€�\’进行转义ã€�
· 在行的末端写入新行ã€�
注意,要写入FIELDS ESCAPED BY â€�\\’,您必须为待读取的值指定两个反斜杠,作为一个单反斜杠使用ã€�
注释:如果您已经åœ�Windows系统中生成了文本文件,您可能必须使用LINES TERMINATED BY â€�\r\n’来正确地读取文件,因为Windows程序通常使用两个字符作为一个行终止符。部分程序,比如WordPad,当编写文件时,可能会使ç”�\r作为行终止符。要读取这样的文件,应使ç”�LINES TERMINATED BY â€�\r’ã€�
如果所有您希望读入的行都含有一个您希望忽略的共用前缀,则您可以使ç”�'prefix_string'来跳过前缀(和前缀前的字符)。如果某行不包括前缀,则整个行被跳过。注释:prefix_string会出现在一行的中间ã€�
示例ï¼�
mysql> LOAD DATA INFILE '/tmp/test.txt'
-> INTO TABLE test LINES STARTING BY "xxx";
使用此语句,您可以读入包含有如下内容的文件:
xxx"row",1
something xxx"row",2
并只得到数据("row",1)å’�("row",2)ã€�
IGNORE number LINES选项可以被用于在文件的开始处忽略行。例如,您可以使ç”�IGNORE 1 LINES来跳过一个包含列名称的起始标题行ï¼�
mysql> LOAD DATA INFILE '/tmp/test.txt'
-> INTO TABLE test IGNORE 1 LINES;
当您联合使用SELECT...INTO OUTFILEå’�LOAD DATA INFILE来从一个数据库中把数据写入一个文件中,然后再读取文件,返回到数据库中时,用于两个语句çš�field-å’�line-handling选项必须匹配。否则,LOAD DATA INFILE不会正确地理解文件的内容。假设您使用SELECT...INTO OUTFILE来编写一个的文件,字段由逗号分隔ï¼�
mysql> SELECT * INTO OUTFILE 'data.txt'
-> FIELDS TERMINATED BY ','
-> FROM table2;
要读取由逗号分隔的文件并返回,则正确的语句应该是ï¼�
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
-> FIELDS TERMINATED BY ',';
如果您尝试使用以下所示的语句读入文件,则不会运行,因为该语句命令LOAD DATA INFILE寻找位于字段之间的制表符ï¼�
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
-> FIELDS TERMINATED BY '\t';
结果很可能是,每个输入行被理解为一个单一字段ã€�
LOAD DATA INFILE也可以被用于读取从外源中获取的文件。例如,一ä¸�dBASE格式的文件具有以逗号分隔并且包含在双引号中的字段。如果文件中的各行以新行为结尾,则此处所示的语句描述了您可以用于载入文件çš�field-å’�line-handling选项ï¼�
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
-> FIELDS TERMINATED BY ',' ENCLOSED BY '"'
-> LINES TERMINATED BY '\n';
所æœ�field-æˆ�line-handling选项都可以指定一个空字符ä¸�('')。如果字符串不是空的,则FIELDS [OPTIONALLY] ENCLOSED BYå’�FIELDS ESCAPED BY值必须为单一字符ã€�FIELDS TERMINATED BY, LINES STARTING BYå’�LINES TERMINATED BY值可以超过一个字符。例如,要编写由回车/换行成对字符作为结尾的行,或读取包含这类行的文件,则应指定一ä¸�LINES TERMINATED BY â€�\r\n’子句ã€�
如果jokes被由%%组成的行分隔ï¼�要读取包å��jokes的文件,您可以这么操作:
mysql> CREATE TABLE jokes
-> (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> joke TEXT NOT NULL);
mysql> LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes
-> FIELDS TERMINATED BY ''
-> LINES TERMINATED BY '\n%%\n' (joke);
FIELDS [OPTIONALLY] ENCLOSED BY用于控制字段的引号。对于(SELECT...INTO OUTFILE),如果您忽略了词语OPTIONALLY,则所有的字段都被包含åœ�ENCLOSED BY字符串中。此处展示了此类输出的一个示例(使用逗号作为字段分隔符)ï¼�
"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"
如果您指定了OPTINALLY,则ENCLOSED BY字符只被用于包含具有字符串数据类型(比如CHAR, BINARY, TEXTæˆ�ENUM)的列中的值:
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20
注意,如果在字段值内出现ENCLOSED BY字符,则通过使用ESCAPED BY字符作为前缀,对ENCLOSED BY字符进行转义。另外,要注意,如果您指定了一个空çš�ESCAPED BY值,则可能会生成不能è¢�LOAD DATA INFILE正确读取的输出值。例如,如果转义符为空字符,则刚显示的先前输出值应显示如下。请观察,第四行中的第二个字段在引号后面包含一个逗号,该引号(错误地)显示出来,作为字段的结尾:
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20
对于输入值,ENCLOSED BY字符被从字段字的末尾剥离。(不论OPTIONALLY是否被指定都会剥离;OPTIONALLY对输入值的解释没有影响。)如果ENCLOSED BY字符前面带有ESCAPED BY字符,则被理解为当前字段值的一部分ã€�
如果字段ä»�ENCLOSED BY字符为开始,当出现这类字符时,只有后面接着字段或行TERMINATED BY序列时,这类字符被认为是一个字段值的结尾。为了避免意思不明确,当在一个字段值中出现ENCLOSED BY字符时,此字符可以重复书写,并被理解为单一的字符。例如,如果指定äº�ENCLOSED BY '"',则按照以下方法操作引号ï¼�
"The ""BIG"" boss" -> The "BIG" boss
The "BIG" boss -> The "BIG" boss
The ""BIG"" boss -> The ""BIG"" boss
FIELDS ESCAPED BY用于控制如何写入或读取特殊字符。如æž�FIELDS ESCAPED BY字符不是空字符,则可以在输出中用于对以下字符加前缀ï¼�
· FIELDS ESCAPED BY字符
· FIELDS [OPTIONALLY] ENCLOSED BY字符
· FIELDS TERMINATED BYå’�LINES TERMINATED BY值的第一个字ç¬�
· ASCII 0(在转义符之后编写的字符实际上是ASCIIâ€�0’,而不是一个值为0的字节)
如果FIELDS ESCAPED BY字符为空字符,则没有字符被转义,并且NULL被作ä¸�NULL输出,而不æ˜�\N。去指定一个空的转义符不是一个好办法,特别是如果数据的字段值包含任何刚给定的清单中的字符时,更不能这么做ã€�
对于输入值,如果FIELDS ESCAPED BY字符不是空字符,则出现这种字符时会被剥离,然后以下字符被作为字段值的一部分。例外情况是,被转义的â€�0’或â€�N’(例如ï¼�\0æˆ�\N,此时转义符为â€�\’)。这些序列被理解ä¸�ASCII NUL(一个零值字节)å’�NULL。用äº�NULL处理的规则在本节的后部进行说明ã€�
要了解有关â€�\â€�-escape语法的更多信息,请参è§�9.1节,“文字值â€�ã€�
在特定情况下ï¼�field-å’�line-handling选项相互影响ï¼�
· 如果LINES TERMINATED BY是空字符串,并且FIELDS TERMINATED BY不是空字符串,则各行ä»�FIELDS TERMINATED BY作为结尾ã€�
· 如果FIELDS TERMINATED BYå’�FIELDS ENCLOSED BY值均为空å€�(''),则使用固定行(无分隔)格式。使用固定行格式时,在字段之间不使用分隔符(但是您仍然可以有行终止符)。列值使用列的显示宽度进行写入和读取。例如,如果某列被定义为INT(7),则使用7字符字段写入列值。输出时,通过读取7个字符获取列值ã€�
LINES TERMINATED BY仍然用于分隔行。如果某行不包含所有字段,则其余的各列被设置到默认值。如果您没有行终止符,您应该把终止符设置ä¸�''。在此情况下,文本文件必须包含每行的所有字段ã€�
固定行格式也会影å“�NULL值的操作,这将在以后进行介绍。注意,如果您正在使用一个多字节字符集,则固定规格格式不会运行ã€�
根据正在使用中的FIELDSå’�LINES选项的不同,NULL值的操作有所变化ï¼�
· 对于默认çš�FIELDSå’�LINES值,NULL被作ä¸�\N的字段值编写,用于输出ï¼�\N字段值被作为NULL读取,用于输入(假设ESCAPED BY字符为â€�\’)ã€�
· 如果FIELDS ENCLOSED BY不是空值,则包含以文字词语NULL为值的字段被作ä¸�NULL值读取。这与被FIELDS ENCLOSED BY字符包围的词è¯�NULL不同。该词语被作为字符串'NULL'读取ã€�
· 如果FIELDS ESCAPED BY是空值,åˆ�NULL被作为词è¯�NULL写入ã€�
· 采用固定行格式时(当FIELDS TERMINATED BYå’�FIELDS ENCLOSED BY均为空值时采用),NULL被作为一个空字符串写入。注意,这会导致在被写入文件时,表中çš�NULL值和空字符串均无法辨别,这是因为两者都被作为空字符串写入。如果您需要在读取文件并返回时能够分辨两者,则您不应使用固定行格式ã€�
LOAD DATA INFILE不支持有些情况:
· 固定规格行(FIELDS TERMINATED BYå’�FIELDS ENCLOSED BY均为空值)å’�BLOBæˆ�TEXT列ã€�
· 如果您指定了一个分隔符,并且该分隔符与其它的前缀一样,åˆ�LOAD DATA INFILE不能正确地理解输入值。例如,下面çš�FIELDS子句会导致问题:
· FIELDS TERMINATED BY '"' ENCLOSED BY '"'
· 如果FIELDS ESCAPED BY为空值,则包å��FIELDS ENCLOSED BYæˆ�LINES TERMINATED BY的字段值后面再æŽ�FIELDS TERMINATED BY值会导致LOAD DATA INFILE过早地停止读取一个字段或行。出现这种情况的原因æ˜�LOAD DATA INFILE不能正确地决定字段或行值在哪里结束ã€�
以下的例子载入了persondata表中的所有列ï¼�
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
默认情况下,如果åœ�LOAD DATA INFILE语句的末尾处没有设列清单时,则输入行预计会包含一个字段,用于表中的每个列。如果您只想载入一个表的部分列,则应指定一个列清单ï¼�
mysql> LOAD DATA INFILE 'persondata.txt'
-> INTO TABLE persondata (col1,col2,...);
如果输入文件中各字段的顺序与表中各列的顺序不同,您也必须指定一个列清单。否则,MySQL不能把输入字段和表中的列匹配起来ã€�
列清单可以包含列名称或用户变量。支æŒ�SET子句。这使您可以把输入值赋予用户变量,然后在把结果赋予列之前,对这些值进行变捀€�
SET子句中的用户变量可以采用多种方式使用。以下例子使用数据文件中的第一列,直接用于t1.column1的值。在用户变量被用äº�t2.column2值之前,把第二列赋予用户变量。该变量从属于一个分割运行ã€�
LOAD DATA INFILE 'file.txt'
INTO TABLE t1
(column1, @var1)
SET column2 = @var1/100;
SET子句可以被用于提供不是来源于输入文件的值。以下语句把column3设置为当前的日期和时间:
LOAD DATA INFILE 'file.txt'
INTO TABLE t1
(column1, column2)
SET column3 = CURRENT_TIMESTAMP;
您也可以通过把输入值赋予一个用户变量,同时不把变量赋予表中的列,来丢弃此输入值:
LOAD DATA INFILE 'file.txt'
INTO TABLE t1
(column1, @dummy, column2, @dummy, column3);
åˆ�/变量清单å’�SET子句的使用受到以下限定:
· åœ�SET子句中的赋值应只含有位于赋值操作符的左侧的列名称ã€�
· 您可以在SET赋值的右侧使用子查诀€‚如果子查询可以返回一个值,并且此值将被赋予到一个列中,则此子查询只能是标量子查诀€‚另外,您不能使用子查询从一个正在被载入的表中选择ã€�
· 对于于列/变量清单æˆ�SET子句,被IGNORE子句忽略的行不被处理ã€�
· 当载入采用固定行格式的数据时,不能使用用户变量,因为用户变量没有显示宽度ã€�
当处理一个输入行时,LOAD DATA会依据列/变量清单å’�SET子句,把行拆分成字段,并使用值。然后,得到的行被插入表中。如果有用于表的BEFORE INSERTæˆ�AFTER INSERT触发器,则在插入行之前和插入行之后分别启动触发器ã€�
如果一个输入行含有过多的字段,则多余的字段被忽略,并且警告的数量增加ã€�
如果一个输入行含有的字段过少,则输入字段缺失的表中的列被设置为默认值。默认值赋值在13.1.5节,“CREATE TABLE语法â€�中进行了说明ã€�
如果字段值缺失,则对一个空字段值会被按不同方式理解ï¼�
· 对于字符串类型,列被设置为空字符串ã€�
· 对于数字类型,列被设置为0ã€�
· 对于日期和时间类型,列被设置为该类型相应的â€�zero”。请参见11.3节,“日期和时间类型â€�ã€�
如果您明确地把一个空字符串赋予一ä¸�INSERTæˆ�UPDATE语句中的字符串类型、数字类型或日期或时间类型,则产生的这些值相同ã€�
只有在两种情况下TIMESTAMP列被设置为当前日期和时间。一种情况时当列有一ä¸�NULL值(也就æ˜�\N)时;另一种情况是(仅对于第一ä¸�TIMESTAMP列),当一个字段清单被指定时,TIMESTAMP列会从字段清单中被略去ã€�
LOAD DATA INFILE把所有的输入值当作字符串,所以您不能按照使用INSERT语句的方式使ç”�ENUMæˆ�SET列的数字值。所有的ENUMå’�SET值必须被指定为字符串ã€�
å½�LOAD DATA INFILE语句结束时,会按以下格式返回一个信息字符串ï¼�
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
如果您正在使ç”�C API,您可以通过调用mysql_info()函数获取有关语句的信息。请参见25.2.3.34节,“mysql_info()â€�ã€�
当值通过INSERT语句被插入时或出现相同情况时,会发生警告(见13.2.4节,“INSERT语法â€�)。例外情况是,当输入行中字段过多或过少时ï¼�LOAD DATA INFILE也生成警告。这些警告并不存储;警告的数量只用于指示运行是否良好ã€�
您可以使ç”�SHOW WARNINGS来得到第一æ‰�max_error_count警告的清单,作为有关运行错误的信息。请参见13.5.4.22节,“SHOW WARNINGS语法â€�ã€�
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
VALUES ({expr | DEFAULT},...),(...),...
或:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
或:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
SELECT ...
REPLACE的运行与INSERT很相像。只有一点除外,如果表中的一个旧记录与一个用äº�PRIMARY KEY或一ä¸�UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除。请参见13.2.4节,“INSERT语法â€�ã€�
注意,除非表有一ä¸�PRIMARY KEYæˆ�UNIQUE索引,否则,使用一ä¸�REPLACE语句没有意义。该语句会与INSERT相同,因为没有索引被用于确定是否新行复制了其它的行ã€�
所有列的值均取自åœ�REPLACE语句中被指定的值。所有缺失的列被设置为各自的默认值,这和INSERT一样。您不能从当前行中引用值,也不能在新行中使用值。如果您使用一个例如â€�SET col_name = col_name + 1”的赋值,则对位于右侧的列名称的引用会被作ä¸�DEFAULT(col_name)处理。因此,该赋值相当于SET col_name = DEFAULT(col_name) + 1ã€�
为了能够使用REPLACE,您必须同时拥有表的INSERTå’�DELETE权限ã€�
REPLACE语句会返回一个数,来指示受影响的行的数目。该数是被删除和被插入的行数的和。如果对于一个单è¡�REPLACE该数ä¸�1,则一行被插入,同时没有行被删除。如果该数大äº�1,则在新行被插入前,有一个或多个旧行被删除。如果表包含多个唯一索引,并且新行复制了在不同的唯一索引中的不同旧行的值,则有可能是一个单一行替换了多个旧行ã€�
受影响的行数可以容易地确定是å��REPLACE只添加了一行,或者是å��REPLACE也替换了其它行:检查该数是否为1(添加)或更大(替换)ã€�
如果您正在使ç”�C API,则可以使用mysql_affected_rows()函数获得受影响的行数ã€�
目前,您不能在一个子查询中,向一个表中更换,同时从同一个表中选择ã€�
以下是所用算法的更详细的说明(该算法也用äº�LOAD DATA...REPLACE):
1. 尝试把新行插入到表中
2. 当因为对于主键或唯一关键字出现重复关键字错误而造成插入失败时:
a. 从表中删除含有重复关键字值的冲突è¡�
b. 再次尝试把新行插入到表中
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr, ...
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name']
[FROM table_references
[WHERE where_definition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_definition]
[ORDER BY {col_name | expr | position}
[ASC | DESC] , ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[FOR UPDATE | LOCK IN SHARE MODE]]
SELECT用于恢复从一个或多个表中选择的行,并可以加入UNION语句和子查询。请参见13.2.7.2节,“UNION语法
â€�å’�13.2.8节,“Subquery语法â€�ã€�
· 每个select_expr都指示一个您想要恢复的列ã€�
· table_references指示行从哪个表或哪些表中被恢复。在13.2.7.1节,“JOIN语法â€�中对该语法进行了说明ã€�
· where_definition包括关键è¯�WHERE,后面接一个表达式。该表达式指示被选择的行必须满足的条件ã€�
有的行在计算时未引用任何表ã€�SELECT也可以用于恢复这类行ã€�
举例说明ï¼�
mysql> SELECT 1 + 1;
-> 2
所有被使用的子句必须按语法说明中显示的顺序严格地排序。例如,一ä¸�HAVING子句必须位于GROUP BY子句之后,并位于ORDER BY子句之前ã€�
· 使用AS alias_name可以ä¸�select_expr给定一个别名。此别名用作表达式的列名,可以用äº�GROUP BYã€�ORDER BYæˆ�HAVING子句。例如:
· mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
· -> FROM mytable ORDER BY full_name;
在为select_expr给定别名时,AS关键词是自选的。前面的例子可以这样编写ï¼�
mysql> SELECT CONCAT(last_name,', ',first_name) full_name
-> FROM mytable ORDER BY full_name;
因为AS是自选的,如果您忘记在两ä¸�select_expr表达式之间加逗号,则会出现一个小问题ï¼�MySQL会把第二个表达式理解为一个别名。例如,在以下语句中ï¼�columnb被作为别名对待:
mysql> SELECT columna columnb FROM mytable;
因此,使ç”�AS明确地指定列的别名,把它作为习惯,是一个良好的操作规范ã€�
· 在一ä¸�WHERE子句中使用列别名是不允许的,因为当执è¡�WHERE子句时,列值可能还没有被确定。请参见A.5.4节,“与列别名有关的问题â€�ã€�
· FROM table_references子句指示行从哪些表中被恢复。如果您命名的表多于一个,则您在进行一个联合操作。要了解有关联合语法的说明,请参è§�13.2.7.1节,“JOIN语法â€�。对于每一个被指定的表,您可以自选地指定一个别名ã€�
· tbl_name [[AS] alias]
· [{USE|IGNORE|FORCE} INDEX (key_list)]
使用USE INDEXã€�IGNORE INDEXã€�FORCE INDEX可以向优化符提示如何选择索引。这部分内容åœ�13.2.7.1节,“JOIN语法â€�中进行了讨论ã€�
您可以使ç”�SET max_seeks_for_key=value作为一种替代方法,来促ä½�MySQL优先采用关键字扫描,替代表扫描ã€�
· 您可以把当前数据库中的一个表作为tbl_name(在当前数据库中)引用,或作ä¸�db_name.tbl_name引用,来明确地指定一个数据库。您可以把一列作ä¸�col_name, tbl_name.col_name引用或作ä¸�db_name.tbl_name.col_name引用。您不需要对一个列引用指定一ä¸�tbl_nameæˆ�db_name.tbl_name前缀,除非此引用意义不明确。意义不明确时,要求指定明确的列引用格式。有关示例见9.2节,“数据库、表、索引、列和别名â€�ã€�
· 在没有表被引用的情况下,允许您指å®�DUAL作为一个假的表名ã€�
· mysql> SELECT 1 + 1 FROM DUAL;
· -> 2
有些服务器要求一ä¸�FROM子句ã€�DUAL仅用于与这些服务器兼容。如果没有表被引用,åˆ�MySQL不要求该子句,前面的语句可以按以下方法编写:
mysql> SELECT 1 + 1;
-> 2
· 使用tbl_name AS alias_nameæˆ�tbl_name alias_name可以为一个表引用起别名:
· mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
· -> WHERE t1.name = t2.name;
· mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
· -> WHERE t1.name = t2.name;
· åœ�WHERE子句中,您可以使ç”�MySQL支持的所有函数,不过总计(总结)函数除外。请参见ç¬�12章:函数和操作符ã€�
· 被选择的用于输出的列可以使用列名称、列别名或列位置被引用到ORDER BYå’�GROUP BY子句中。列位置为整数,ä»�1开始:
· mysql> SELECT college, region, seed FROM tournament
· -> ORDER BY region, seed;
· mysql> SELECT college, region AS r, seed AS s FROM tournament
· -> ORDER BY r, s;
· mysql> SELECT college, region, seed FROM tournament
· -> ORDER BY 2, 3;
要以相反的顺序进行分类,应把DESC(降序)关键字添加到ORDER BY子句中的列名称中。默认值为升序;该值可以使ç”�ASC关键词明确地指定ã€�
不建议使用列位置,因为该语法已经ä»�SQL标准中删除ã€�
· 如果您使ç”�GROUP BY,则输出行根æ��GROUP BY列进行分类,如同您对相同的列进行äº�ORDER BYã€�MySQLå¯�GROUP BY进行了扩展,因此您可以在各列(在子句中进行命名)的后面指å®�ASCå’�DESCï¼�
· SELECT a, COUNT(b) FROM test_table GROUP BY a DESC
·
MySQLå¯�GROUP BY的使用进行了扩展,允许选择åœ�GROUP
BY子句中没有被提到的字段。如果您没有得到预期的结果,请阅è¯�GROUP BY的说明,请参è§�12.10节,“与GROUP BY子句同时使用的函数和修改程序â€�ã€�
· GROUP BY允许一ä¸�WITH ROLLUP修饰符。请参见12.10.2节,“GROUP BY修改程序â€�ã€�
· HAVING子句基本上是最后使用,只位于被发送给客户端的条目之前,没有进行优化。(LIMIT用于HAVING之后。)
SQL标准要求HAVING必须引用GROUP BY子句中的列或用于总计函数中的列。不过,MySQL支持对此工作性质的扩展,并允è®�HAVING因为SELECT清单中的列和外部子查询中的列ã€�
如果HAVING子句引用了一个意义不明确的列,则会出现警告。在下面的语句中ï¼�col2意义不明确,因为它既作为别名使用,又作为列名使用ï¼�
mysql> SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;
标准SQL工作性质具有优先权,因此如果一ä¸�HAVING列名既被用于GROUP BY,又被用作输出列清单中的起了别名的列,则优先权被给予GROUP BY列中的列ã€�
· HAVING不能用于应被用于WHERE子句的条目。例如,不能编写如下语句ï¼�
· mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;
而应这么编写ï¼�
mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;
· HAVING子句可以引用总计函数,è€�WHERE子句不能引用ï¼�
· mysql> SELECT user, MAX(salary) FROM users
· -> GROUP BY user HAVING MAX(salary)>10;
(在有些较早版本çš�MySQL中,本语句不运行。)
· LIMIT子句可以被用于限制被SELECT语句返回的行数ã€�LIMIT取一个或两个数字自变量,自变量必须是非负的整数常数(当使用已预备的语句时除外)ã€�
使用两个自变量时,第一个自变量指定返回的第一行的偏移量,第二个自变量指定返回的行数的最大值。初始行的偏移量ä¸�0(不æ˜�1):
mysql> SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
为了ä¸�PostgreSQL兼容ï¼�MySQL也支æŒ�LIMIT row_count OFFSET offset语法ã€�
如果要恢复从某个偏移量到结果集合的末端之间的所有的行,您可以对第二个参数是使用比较大的数。本语句可以恢复从第96行到最后的所有行ï¼�
mysql> SELECT * FROM tbl LIMIT 95,18446744073709551615;
使用1个自变量时,该值指定从结果集合的开头返回的行数ï¼�
mysql> SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
换句话说ï¼�LIMIT nä¸�LIMIT 0,n等价ã€�
对于已预备的语句,您可以使用位置保持符。以下语句将ä»�tb1表中返回一行:
mysql> SET @a=1;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?";
mysql> EXECUTE STMT USING @a;
以下语句将从tb1表中返回第二到第六行ï¼�
mysql> SET @skip=1; SET @numrows=5;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?, ?";
mysql> EXECUTE STMT USING @skip, @numrows;
· SELECT...INTO OUTFILE 'file_name'形式çš�SELECT可以把被选择的行写入一个文件中。该文件被创建到服务器主机上,因此您必须拥有FILE权限,才能使用此语法ã€�file_name不能是一个原有的文件。原有文件会阻止例如â€�/etc/passwd”的文件和数据库表被销毁ã€�
SELECT...INTO OUTFILE语句的主要作用是让您可以非常快速地把一个表转储到服务器机器上。如果您想要在服务器主机之外的部分客户主机上创建结果文件,您不能使用SELECT...INTO OUTFILE。在这种情况下,您应该在客户主机上使用比如â€�mysql â€�e "SELECT ..." > file_name”的命令,来生成文件ã€�
SELECT...INTO OUTFILEæ˜�LOAD DATA INFILE的补语;用于语句çš�exort_options部分的语法包括部åˆ�FIELDSå’�LINES子句,这些子句与LOAD DATA INFILE语句同时使用。请参见13.2.5节,“LOAD DATA INFILE语法â€�ã€�
FIELDS ESCAPED BY用于控制如何写入特殊字符。如æž�FIELDS ESCAPED BY字符不是空字符,则被用于在输出中对以下字符设前缀ï¼�
o FIELDS ESCAPED BY字符
o FIELDS [OPTIONALLY] ENCLOSED BY字符
o FIELDS TERMINATED BYå’�LINES TERMINATED BY值的第一个字ç¬�
o ASCII 0(在编写时接在转义符后面的是ASCII â€�0’,而不是一个零值字节)
如果FIELDS ESCAPED BY字符是空字符,则没有字符被转义,并且NULL被作ä¸�NULL输出,而不是作ä¸�\N输出。指定一个空的转义符不是一个好的主意。特别是当您的数据中的字段值包含刚被给予的清单中的字符时,更是如此ã€�
其原因是您必须对所æœ�FIELDS TERMINATED BY, ENCLOSED BY, ESCAPED BYæˆ�LINES TERMINATED BY字符进行转义,才能可靠地读取文件并返回ã€�ASCII NUL被转义,以便更容易地使用调页程序观看ã€�
生成的文件不必符å��SQL语法,所以没有其它的字符需要被转义ã€�
在下面的例子中,生成一个文件,各值用逗号隔开。这种格式可以被许多程序使用ã€�
SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM test_table;
· 如果您使ç”�INTO DUMPFILE代替INTO OUTFILE,则MySQL只把一行写入到文件中,不对任何列或行进行终止,也不执行任何转义处理。如果您想要把一ä¸�BLOB值存储到文件中,则这个语句是有用的ã€�
· 注释:任何由INTO OUTFILEæˆ�INTO DUMPFILE创建的文件都可以被服务器主机上的所有用户编写。原因是ï¼�MySQL服务器不能创建这样的文件,即文件的所有者不是该文件运行时所属的用户(任何时候,您都不能出于此原因或出于其它原因æŠ�mysqld作为根段运行)。该文件必须是全局可写的,这样您就可以操作其中的内容ã€�
· 有的过程应在结果集合内处理数据ã€�PROCEDURE子句用于对这些过程进行命名。要了解示例,请参见27.3.1节,“步骤分析â€�ã€�
· 存储引擎使用页面或行锁。如果您对存储引擎使ç”�FOR UPDATE,则受到查询检验的行会被进行写锁定,直到当前事务结束为歀€‚使ç”�LOCK IN SHARE MODE可以设置一个共享锁。共享锁可以防止其它事务更新或删除被检验的行。请参见15.2.10.5节,“锁定读取SELECT ... FOR UPDATE和SELECT ... LOCK IN SHARE MODEâ€�ã€�
åœ�SELECT关键词的后面,您可以使用许多选项。这些选项可以影响语句的运行ã€�
ALL, DISTINCTå’�DISTINCTROW选项指定是否重复行应被返回。如果这些选项没有被给定,则默认值为ALL(所有的匹配行被返回)ã€�DISTINCTå’�DISTINCTROW是同义词,用于指定结果集合中的重复行应被删除ã€�
HIGH_PRIORITY, STRAIGHT_JOIN和以SQL_为开头的选项æ˜�MySQL相对于标å‡�SQL的扩展ã€�
· HIGH_PRIORITY给予SELECT更高的优先权,高于用于更新表的语句。您应该只对查询使用HIGH_PRIORITY。查询速度非常快,而且立刻被执行ã€�SELECT HIGH_PRIORITY查询在表被锁定用于读取时被发出。即使有一个新的语句正在等待表变为空闲,查询也会运行ã€�
HIGH_PRIORITY不能å’�SELECT语句同时使用ã€�SELECT语句æ˜�UNION的一部分ã€�
·
STRAIGHT_JOIN用于促使优化符把表联合在一起,顺序按照这些表在FROM子句中排列的顺序。如果优化符联合表时顺序不佳,您可以使用STRAIGHT_JOIN来加快查询的速度。请参见7.2.1节,“EXPLAIN语法(获取关于SELECT的信息)â€�ã€�STRAIGHT_JOIN也可以被用于table_references清单中。请参见13.2.7.1节,“JOIN语法â€�ã€�
· SQL_BIG_RESULT可以ä¸�GROUP BYæˆ�DISTINCT同时使用,来告知优化符结果集合有很多行。在这种情况下,MySQL直接使用以磁盘为基础的临时表(如果需要的话)。在这种情况下,MySQL还会优先进行分类,不优先使用临时表。临时表对于GROUP BY组分带有关键字ã€�
· SQL_BUFFER_RESULT促使结果被放入一个临时表中。这可以帮助MySQL提前解开表锁定,在需要花费较长时间的情况下,也可以帮助把结果集合发送到客户端中ã€�
· SQL_SMALL_RESULT可以ä¸�GROUP BYæˆ�DISTINCT同时使用,来告知优化符结果集合是较小的。在此情况下ï¼�MySAL使用快速临时表来储存生成的表,而不是使用分类。在MySQL 5.1中,通常不需要这样ã€�
· SQL_CALC_FOUND_ROWS告知MySQL计算有多少行应位于结果集合中,不考虑任何LIMIT子句。行的数目可以使ç”�SELECT FOUND_ROWS()恢复。请参见12.9.3节,“信息函数â€�ã€�
· 如果您正在使用一ä¸�query_cache_type值,值为2æˆ�DEMAND,则SQL_CACHE告知MySQL把查询结果存储在查询缓存中。对于使ç”�UNION的查询或子查询,本选项会影响查询中的所æœ�SELECT。请参见5.13节,“MySQL查询高速缓冲â€�ã€�
· SQL_NO_CACHE告知MySQL不要把查询结果存储在查询缓存中。请参见5.13节,“MySQL查询高速缓冲â€�。对于一个使ç”�UNION或子查询的查询,本选项会影响查询中çš�SELECTã€�
MySQL支持以下JOIN语法。这些语法用äº�SELECT语句çš�table_references部分和多è¡�DELETEå’�UPDATE语句ï¼�
table_references:
table_reference [, table_reference] �
table_reference:
table_factor
| join_table
table_factor:
tbl_name [[AS] alias]
[{USE|IGNORE|FORCE} INDEX (key_list)]
| ( table_references )
| { OJ table_reference LEFT OUTER JOIN table_reference
ON conditional_expr }
join_table:
table_reference [INNER | CROSS] JOIN table_factor [join_condition]
| table_reference STRAIGHT_JOIN table_factor
| table_reference STRAIGHT_JOIN table_factor ON condition
| table_reference LEFT [OUTER] JOIN table_reference join_condition
| table_reference NATURAL [LEFT [OUTER]] JOIN table_factor
| table_reference RIGHT [OUTER] JOIN table_reference join_condition
| table_reference NATURAL [RIGHT [OUTER]] JOIN table_factor
join_condition:
ON conditional_expr
| USING (column_list)
一个表引用还被称为一个联合表达式ã€�
ä¸�SQL标准相比ï¼�table_factor的语法被扩展了ã€�SQL标准只接å��table_reference,而不是圆括号内的一系列条目ã€�
如果我们把一系列table_reference条目中的每个逗号都看作相当于一个内部联合,则这是一个稳妥的扩展。例如:
SELECT * FROM t1 LEFT JOIN (t2, t3, t4)
ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
相当于:
SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)
ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
åœ�MySQL中,CROSS JOIN从语法上说与INNER JOIN等同(两者可以互相替捀€‚在标准SQL中,两者是不等同的ã€�INNER JOINä¸�ON子句同时使用ï¼�CROSS JOIN以其它方式使用ã€�
通常,在只含有内部联合运行的联合表达式中,圆括号可以被忽略ã€�MySQL也支持嵌套的联合(见7.2.10节,“MySQL如何优化嵌套Joinâ€�)ã€�
通常,您不应å¯�ON部分有任何条件ã€�ON部分用于限定在结果集合中您想要哪些行。但是,您应åœ�WHERE子句中指定这些条件。这条规则有一些例外ã€�
在前面的清单中显示的{ OJ ... LEFT OUTER JOIN ...}语法的目的只是为了保持与ODBC的兼容性。语法中的花括号应按字面书写;该括号不是中间语法。中间语法用于语法描述的其它地方ã€�
· 表引用可以使ç”�tbl_name AS alias_nameæˆ�tbl_name alias_name指定别名ï¼�
· mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
· -> WHERE t1.name = t2.name;
· mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
· -> WHERE t1.name = t2.name;
· ON条件句是可以被用äº�WHERE子句的格式的任何条件表达式ã€�
· 如果对于åœ�LEFT JOIN中的ONæˆ�USING部分中的右表没有匹配的记录,则所有列被设置为NULL的一个行被用于右表。如果一个表在其它表中没有对应部分,您可以使用这种方法在这种表中查找记录ï¼�
· mysql> SELECT table1.* FROM table1
· -> LEFT JOIN table2 ON table1.id=table2.id
· -> WHERE table2.id IS NULL;
本例查找åœ�table1中含有一ä¸�id值的所有行。同时,åœ�table2中没有此id值(即,table1中的所有行åœ�table2中没有对应的行)。本例假è®�table2.id被定义为NOT NULL。请参见7.2.9节,“MySQL如何优化LEFT JOIN和RIGHT JOINâ€�ã€�
· USING(column_list)子句用于为一系列的列进行命名。这些列必须同时在两个表中存在。如果表a和表b都包含列c1, c2å’�c3,则以下联合会对比来自两个表的对应的列:
· a LEFT JOIN b USING (c1,c2,c3)
· 两个表的NATURAL [LEFT] JOIN被定义为ä¸�INNER JOIN语义相同,或与使ç”�USING子句çš�LEFT JOIN语义相同ã€�USING子句用于为同时存在于两个表中的所有列进行命名ã€�
· INNER JOIN和,(逗号)在无联合条件下是语义相同的:两者都可以对指定的表计算出笛卡儿乘积(也就是说,第一个表中的每一行被联合到第二个表中的每一行)ã€�
· RIGHT JOIN的作用与LEFT JOIN的作用类似。要使代码可以在数据库内移植,建议您使用LEFT JOIN代替RIGHT JOINã€�
· STRAIGHT_JOINä¸�JOIN相同。除了有一点不一样,左表会在右表之前被读取ã€�STRAIGH_JOIN可以被用于这样的情况,即联合优化符以错误的顺序排列表ã€�
您可以提供提示,当从一个表中恢复信息时ï¼�MySQL应使用哪个索引。通过指定USE INDEXï¼�key_list),您可以告çŸ�MySQL只使用一个索引来查找表中的行。另一种语æ³�IGNORE INDEXï¼�key_list)可以被用于告知MySQL不要使用某些特定的索引。如æž�EXPLAIN显示MySQL正在使用来自索引清单中的错误索引时,这些提示会有用处ã€�
您也可以使用FORCE INDEX,其作用接近USE INDEXï¼�key_list),不过增加了一项作用,一次表扫描被假设为代价很高。换句话说,只有当无法使用一个给定的索引来查找表中的行时,才使用表扫描ã€�
USE KEYã€�IGNORE KEYå’�FORCE KEYæ˜�USE INDEXã€�IGNORE INDEXå’�FORCE INDEX的同义词ã€�
注释:当MySQL决定如何在表中查找行并决定如何进行联合时,使ç”�USE INDEXã€�IGNORE INDEXå’�FORCE INDEX只会影响使用哪些索引。当分解一ä¸�ORDER BYæˆ�GROUP BY时,这些语句不会影响某个索引是否被使用ã€�
部分的联合示例:
mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id);
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
-> LEFT JOIN table3 ON table2.id=table3.id;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
-> WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
-> WHERE key1=1 AND key2=2 AND key3=3;
è§�7.2.9节,“MySQL如何优化LEFT JOIN和RIGHT JOINâ€�ã€�
注释:自然联合和使用USING的联合,包括外部联合变量,依æ��SQL:2003标准被处理。这些变更时MySQL与标å‡�SQL更加相符。不过,对于有些联合,这些变更会导致不同的输出列。另外,有些查询在旧版本ï¼�5.0.12以前)工作正常,但也必须重新编写,以符合此标准。对于有关当前联合处理和旧版本中的联合处理的效果的对比,以下列表提供了更详细的信息ã€�
· NATURAL联合æˆ�USING联合的列会与旧版本不同。特别是,不再出现冗余的输出列,用于SELECT *扩展的列的顺序会与以前不同ã€�
示例ï¼�
CREATE TABLE t1 (i INT, j INT);
CREATE TABLE t2 (k INT, j INT);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t2 VALUES(1,1);
SELECT * FROM t1 NATURAL JOIN t2;
SELECT * FROM t1 JOIN t2 USING (j);
对于旧版本,语句会产生以下输出:
+------+------+------+------+
| i | j | k | j |
+------+------+------+------+
| 1 | 1 | 1 | 1 |
+------+------+------+------+
+------+------+------+------+
| i | j | k | j |
+------+------+------+------+
| 1 | 1 | 1 | 1 |
+------+------+------+------+
在第一ä¸�SELECT语句中,åˆ�i同时出现在两个表中,为一个联合列,所以,依据标准SQL,该列在输出中只出现一次。与此类似,在第二个SELECT语句中,åˆ�jåœ�USING子句中被命名,应在输出中只出现一次。但是,在两种情况下,冗余的列均没被消除。另外,依据标准SQL,列的顺序不正确ã€�
现在,语句产生如下输出:
+------+------+------+
| j | i | k |
+------+------+------+
| 1 | 1 | 1 |
+------+------+------+
+------+------+------+
| j | i | k |
+------+------+------+
| 1 | 1 | 1 |
+------+------+------+
冗余的列被消除,并且依据标准SQL,列的顺序是正确的:
o 第一,两表共有的列,按在第一个表中的顺序排列
o 第二,第一个表中特有的列,按该表中的顺序排åˆ�
o 第三,第二个表中特有的列,按该表中的顺序排列
· 对多方式自然联合的估算会不同。方式要求重新编写查诀€‚假设您有三个表t1(a,b), t2(c,b)å’�t3(a,c),每个表有一行:t1(1,2), t2(10,2)å’�t3(7,10)。同时,假设这三个表具有NATURAL JOINï¼�
· SELECT â€� FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;
在旧版本中,第二个联合的左操作数被认为是t2,然而它应该为嵌套联合(t1 NATURAL JOIN t2)。结果,å¯�t3的列进行检查时,只检查其åœ�t2中的共有列。如æž�t3ä¸�t1有共有列,这些列不被用作equi-join列。因此,在旧版本çš�MySQL中,前面的查询被转换为下面的equi-joinï¼�
SELECT � FROM t1, t2, t3
WHERE t1.b = t2.b AND t2.c = t3.c;
此联合又省略了一ä¸�equi-join谓语ï¼�t1.a = t3.a)。结果是,该联合产生一个行,而不是空结果。正确的等价查询如下ï¼�
SELECT � FROM t1, t2, t3
WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;
如果您要求在当前版本çš�MySQL中获得和旧版本中相同的查询结果,应把自然联合改写为第一ä¸�equi-joinã€�
· 在旧版本中,逗号操作符(,)å’�JOIN均有相同的优先权,所以联合表达式t1, t2 JOIN t3被理解为((t1, t2) JOIN t3)。现在,JOIN有更高的优先权,所以表达式被理解为(t1, (t2 JOIN t3))。这个变更会影响使用ON子句的语句,因为该子句只参阅联合操作数中的列。优先权的变更改变了对什么是操作数的理解ã€�
示例ï¼�
CREATE TABLE t1 (i1 INT, j1 INT);
CREATE TABLE t2 (i2 INT, j2 INT);
CREATE TABLE t3 (i3 INT, j3 INT);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t2 VALUES(1,1);
INSERT INTO t3 VALUES(1,1);
SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);
在旧版本中,SELECT是合法的,因ä¸�t1, t2被隐含地归为(t1,t2)。现在,JOIN取得了优先权,因此用äº�ON子句的操作数æ˜�t2å’�t3。因ä¸�t1.i1不是任何一个操作数中的列,所以结果是出现åœ�'on clause'中有未知åˆ�'t1.i1'的错误。要使联合可以被处理,用使用圆括号把前两个表明确地归为一组,这样用于ON子句的操作数ä¸�(t1,t2)å’�t3ï¼�
SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);
本变更也适用äº�INNER JOINï¼�CROSS JOINï¼�LEFT JOINå’�RIGHT JOINã€�
· 在旧版本中,ON子句可以参阅在其右边命名的表中的列。现在,ON子句只能参阅操作数ã€�
示例ï¼�
CREATE TABLE t1 (i1 INT);
CREATE TABLE t2 (i2 INT);
CREATE TABLE t3 (i3 INT);
SELECT * FROM t1 JOIN t2 ON (i1 = i3) JOIN t3;
在旧版本中,SELECT语句是合法的。现在该语句会运行失败,出现åœ�'on clause'中未知列'i3'的错误。这是因ä¸�i3æ˜�t3中的一个表,è€�t3不是ON子句中的操作数。本语句应进行如下改写:
SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i3);
· 在旧版本中,一ä¸�USING子句可以被改写为一ä¸�ON子句ã€�ON子句对比了相应的列。例如,以下两个子句具有相同的语义:
· a LEFT JOIN b USING (c1,c2,c3)
· a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3
现在,这两个子句不再是一样的ï¼�
o 在决定哪些行满足联合条件时,两个联合保持语义相同ã€�
o 在决定哪些列显示SELECT *扩展时,两个联合的语义不相同ã€�USING联合选择对应列中的合并值,è€�ON联合选择所有表中的所有列。对于前面的USING联合ï¼�SELECT *选择这些值:
o COALESCE(a.c1,b.c1), COALESCE(a.c2,b.c2), COALESCE(a.c3,b.c3)
对于ON联合ï¼�SELECT *选择这些值:
a.c1, a.c2, a.c3, b.c1, b.c2, b.c3
使用内部联合时,COALESCE(a.c1,b.c1)ä¸�a.c1æˆ�b.c1相同,因为两列将具有相同的值。使用外部联合时(比å¦�LEFT JOIN),两列中有一列可以为NULL。该列将会从结果中被忽略ã€�
SELECT ...
UNION [ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT]
SELECT ...]
UNION用于把来自许å¤�SELECT语句的结果组合到一个结果集合中ã€�
列于每个SELECT语句的对应位置的被选择的列应具有相同的类型。(例如,被第一个语句选择的第一列应和被其它语句选择的第一列具有相同的类型。)在第一ä¸�SELECT语句中被使用的列名称也被用于结果的列名称ã€�
SELECT语句为常规的选择语句,但是受到如下的限定ï¼�
· 只有最后一ä¸�SELECT语句可以使用INTO OUTFILEã€�
· HIGH_PRIORITY不能与作ä¸�UNION一部分çš�SELECT语句同时使用。如果您对第一ä¸�SELECT指定äº�HIGH_PRIORITY,则不会起作用。如果您对其它后续的SELECT语句指定äº�HIGH_PRIORITY,则会产生语法错误ã€�
如果您对UNION不使用关键词ALL,则所有返回的行都是唯一的,如同您已经对整个结果集合使用äº�DISTINCT。如果您指定äº�ALL,您会从所有用过的SELECT语句中得到所有匹配的行ã€�
DISTINCT关键词是一个自选词,不起任何作用,但是根据SQL标准的要求,在语法中允许采用。(åœ�MySQL中,DISTINCT代表一个共用体的默认工作性质。)
您可以在同一查询中混å��UNION ALLå’�UNION DISTINCT。被混合çš�UNION类型按照这样的方式对待,å��DISTICT共用体覆盖位于其左边的所æœ�ALL共用体ã€�DISTINCT共用体可以使ç”�UNION DISTINCT明确地生成,或使ç”�UNION(后面不åŠ�DISTINCTæˆ�ALL关键词)隐含地生成ã€�
如果您想使用ORDER BYæˆ�LIMIT子句来对全部UNION结果进行分类或限制,则应对单个地SELECT语句加圆括号,并æŠ�ORDER BYæˆ�LIMIT放到最后一个的后面。以下例子同时使用了这两个子句:
(SELECT a FROM tbl_name WHERE a=10 AND B=1)
UNION
(SELECT a FROM tbl_name WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;
这种ORDER BY不能使用包括表名称(也就是,采用tbl_name.col_name格式的名称)列引用。可以在第一ä¸�SELECT语句中提供一个列别名,并åœ�ORDER BY中参阅别名,或使用列位置åœ�ORDER BY中参阅列。(首选采用别名,因为不建议使用列位置。)
另外,如果带分类的一列有别名,则ORDER BY子句必须引用别名,而不能引用列名称。以下语句中的第一个语句必须运行,但是第二个会运行失败,出现在'order clause'中有未知åˆ�'a'的错误:
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT: 为了对单ä¸�SELECT使用ORDER BYæˆ�LIMIT,应把子句放入圆括号中。圆括号包含äº�SELECTï¼�
(SELECT a FROM tbl_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM tbl_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
圆括号中用于单个SELECT语句çš�ORDER BY只有当与LIMIT结合后,才起作用。否则,ORDER BY被优化去除ã€�
UNION结果集合中的列的类型和长度考虑了被所æœ�SELECT语句恢复的数值。例如,考虑如下语句ï¼�
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a |
| bbbbbbbbbb |
+---------------+
(在部分早期版本çš�MySQL中,第二行已被删节到长度ä¸�1。)
子查询是另一个语句中的一ä¸�SELECT语句ã€�
MySQL支持SQL标准要求的所有子查询格式和操作,也支æŒ�MySQL特有的几种特性ã€�
以下是一个子查询的例子:
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
在本例中ï¼�SELECT * FROM t1...是外部查询(或外部语句),ï¼�SELECT column1 FROM t2)是子查诀€‚我们可以说子查询嵌套在外部查询中。实际上,子查询也可以嵌套在其它子查询中,嵌套程度可以很深。子查询必须要位于圆括号中ã€�
子查询的主要优势为:
· 子查询允许结构化的查询,这样就可以把一个语句的每个部分隔离开ã€�
· 有些操作需要复杂的联合和关联。子查询提供了其它的方法来执行这些操作ã€�
· 在许多人看来,子查询是可读的。实际上,子查询给予人们调用早期SQL“结构化查询语言”的原本的想法,这是子查询的创新ã€�
以下是一个示例语句。该语句显示了有关子查询语法的要点。子查询语法ç”�SQL标准指定并被MySQL支持ã€�
DELETE FROM t1
WHERE s11 > ANY
(SELECT COUNT(*) /* no hint */ FROM t2
WHERE NOT EXISTS
(SELECT * FROM t3
WHERE ROW(5*t2.s1,77)=
(SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
(SELECT * FROM t5) AS t5)));
一个子查询会返回一个标量(单一值)、一个行、一个列或一个表(一行或多行及一列或多列)。这些子查询被称为标量、列、行和表子查诀€‚可返回一个特定种类结果的子查询经常只被用于特定的语境中,在后面各节中有说明ã€�
有些语句可以使用子查诀€‚对这些语句的类型基本没有限定。子查询可以包括普é€�SELECT可以包括的任何关键词或子句:DISTINCT, GROUP BY, ORDER BY, LIMIT, 联合, 索引提示, UNION结构åŒ�, 评注和函数等ã€�
有一个限定是,一个子查询的外部语句必须是以下语句之一ï¼�SELECT, INSERT, UPDATE, DELETE, SETæˆ�DO。还有一个限定是,目前,您不能在一个子查询中修改一个表,又在同一个表中选择。这适用äº�DELETE, INSERT, REPLACEå’�UPDATE语句。在附录Iï¼�特性限åˆ�中给出了对子查询使用的更综合的讨论ã€�
CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
INSERT INTO t1 VALUES(100, 'abcde');
SELECT (SELECT s2 FROM t1);
在本SELECT中的子查询返回一个单一å€�('abcde')。该单一值的数据类型ä¸�CHAR,长度为5,字符集和整序与åœ�CREATE TABLE时有效的默认值相同,并有一个指示符号,指示列中的值可以为NULL。实际上,基本上所有的子查询都ä¸�NULL。如果在本例中使用的表为空表,则子查询的值应ä¸�NULLã€�
在有些情况下,标量子查询不能使用。如果一个语句只允许一个文字值,您不能使用子查询。例如,LIMIT要求文字整数自变量,LOAD DATA要求一个文字字符串文件名。您不能使用子查询来提供这些值ã€�
后面各节包括更简练的结构ï¼�SELECT column1 FROM t1)。当您在这些章节中观看例子时,请设想一下您自己的代码包含更多样、更复杂的结构ã€�
举例说明,假设我们制作两个表ï¼�
CREATE TABLE t1 (s1 INT);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (s1 INT);
INSERT INTO t2 VALUES (2);
然后执行一ä¸�SELECTï¼�
SELECT (SELECT s1 FROM t2) FROM t1;
结果ä¸�2,因ä¸�t2中有一行包å��s1ï¼�s1有一个值为2ã€�
一个标量子查询可以为一个表达式的一部分。不要忘记圆括号。即使是子查询是一个为函数提供自变量的操作数时,也不要忘记圆括号。举例说明:
SELECT UPPER((SELECT s1 FROM t1)) FROM t2;
子查询最常见的一种使用方式如下:
non_subquery_operand comparison_operator (subquery)
å½�comparison_operator是以ä¸� 操作符之一时:
= > < >= <= <>
例如ï¼�
... 'a' = (SELECT column1 FROM t1)
有时,子查询的合法位置只能在比较式的右侧,您可以发现,在有些旧的DBMSs中仍保持这一点ã€�
以下是一个常见格式的子查询比较的例子。您不能使用联合进行此类比较。表t1中有些值与è¡�t2中的最大值相同。该比较可以查找出所有这类值:
SELECT column1 FROM t1
WHERE column1 = (SELECT MAX(column2) FROM t2);
下面还有另一个例子,该例子也不可能使用联合,因为该例子涉及对其中一个表进行总计。表t1中的有些行含有的值会在给定的列中出现两次。该例子可以查找出所有这些行ï¼�
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
对于采用这些操作符之一进行的比较,子查询必须返回一个标量。有一个例外,那就是=可以和行子查询同时使用。请参见13.2.8.5节,“行子查询â€�ã€�
语法ï¼�
operand comparison_operator ANY (subquery)
operand IN (subquery)
operand comparison_operator SOME (subquery)
ANY关键词必须后面接一个比较操作符ã€�ANY关键词的意思是“对于在子查询返回的列中的任一数值,如果比较结果ä¸�TRUE的话,则返回TRUE”。例如:
SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);
假设è¡�t1中有一行包含(10)。如果表t2包含ï¼�21ï¼�14ï¼�7),则表达式ä¸�TRUE,因ä¸�t2中有一个值为7,该值小äº�10。如果表t2包含ï¼�20ï¼�10),或者如果表t2为空表,则表达式ä¸�FALSE。如果表t2包含ï¼�NULL, NULL, NULL),则表达式ä¸�UNKNOWNã€�
词语IN是=ANY的别名。因此,这两个语句是一样的ï¼�
SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN (SELECT s1 FROM t2);
不过ï¼�NOT IN不是<> ANY的别名,但是æ˜�<>
ALL的别名。请参见13.2.8.4节,“使用ALL进行子查è¯�â€�ã€�
词语SOMEæ˜�ANY的别名。因此,这两个语句是一样的ï¼�
SELECT s1 FROM t1 WHERE s1 <> ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);
使用词语SOME的机会很少,但是本例显示了为什ä¹�SOME是有用的。对于多数人来说,英语短语â€�a is not equal to any b”的意思是“没有一ä¸�bä¸�a相等”,但是åœ�SQL语法中不是这个意思。该语法的意思是“有部分bä¸�a不相等”。使ç”�<> SOME有助于确认每个人都理解该查询的真正含义ã€�
operand comparison_operator ALL (subquery)
词语ALL必须接在一个比较操作符的后靀€�ALL的意思是“对于子查询返回的列中的所有值,如果比较结果ä¸�TRUE,则返回TRUE。”例如:
SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);
假设è¡�1中有一行包含(10)。如果表t2包含ï¼�-5ï¼�0,+5),则表达式ä¸�TRUE,因ä¸�10æ¯�t2中的所有三个值都大。如果表t2包含ï¼�12ï¼�6ï¼�NULL,-100),则表达式ä¸�FALSE,因为表t2中有一个å€�12大于10。如果表t2包含ï¼�0ï¼�NULLï¼�1),则表达式ä¸�unknownã€�
最后,如果è¡�t2为空表,则结果为TRUE。因此,当表t2为空表时,以下语句为TRUEï¼�
SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);
但是,当è¡�t2为空表时,本语句ä¸�NULLï¼�
SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);
另外,当è¡�t2为空表时,以下语句为NULLï¼�
SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);
通常,包å��NULL值的表和空表为“边缘情况”。当编写子查询代码时,都要考虑您是否把这两种可能性计算在内ã€�
NOT INæ˜�<> ALL的别名。因此,以下两个语句是相同的ï¼�
SELECT s1 FROM t1 WHERE s1 <> ALL (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);
SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);
如果在表t2的一个行中,column1=1并且column2=2,则查询结果均为TRUEã€�
表达式(1ï¼�2)和ROWï¼�1ï¼�2)有时被称为行构造符。两者是等同的,在其它的语境中,也是合法的。例如,以下两个语句在语义上是等同的(但是目前只有第二个语句可以被优化)ï¼�
SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
行构造符通常用于与对能返回两个或两个以上列的子查询进行比较。例如,以下查询可以答复请求,“在è¡�t1中查找同时也存在于表t2中的所有的行”:
SELECT column1,column2,column3
FROM t1
WHERE (column1,column2,column3) IN
(SELECT column1,column2,column3 FROM t2);
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
过去ï¼�EXISTS子查询以SELECT *为开始,但是可以ä»�SELECT 5æˆ�SELECT column1或其它的为开始ã€�MySQL在这类子查询中忽略了SELECT清单,因此没有区别ã€�
对于前面的例子,如果t2包含任何行,即使是只含有NULL值的行,EXISTS条件也为TRUE。这实际上是一个不可能的例子,因为基本上所有的[NOT] EXISTS子查询均包含关联。以下是一些更现实的例子:
· 哪些种类的商店出现在一个或多个城市里?
· SELECT DISTINCT store_type FROM stores
· WHERE EXISTS (SELECT * FROM cities_stores
· WHERE cities_stores.store_type = stores.store_type);
· 哪些种类的商店没有出现在任何城市里?
· SELECT DISTINCT store_type FROM stores
· WHERE NOT EXISTS (SELECT * FROM cities_stores
· WHERE cities_stores.store_type = stores.store_type);
· 哪些种类的商店出现在所有城市里ï¼�
· SELECT DISTINCT store_type FROM stores s1
· WHERE NOT EXISTS (
· SELECT * FROM cities WHERE NOT EXISTS (
· SELECT * FROM cities_stores
· WHERE cities_stores.city = cities.city
· AND cities_stores.store_type = stores.store_type));
最后一个例子是一个双嵌套NOT EXISTS查询。也就是,该查询包含一ä¸�NOT EXISTS子句,该子句又包含在一ä¸�NOT EXISTS子句中。该查询正式地回答了这个问题,“是否有某个城市拥有没有列在Stores中的商店?”。可以比较容易的说,一个带嵌套çš�NOT EXISTS可以回答这样的问题,“是否对于所有的yï¼�x都为TRUE?â€�
SELECT * FROM t1 WHERE column1 = ANY
(SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);
注意,即使子查询çš�FROM子句不提及表t1,该子查询也会包含一个对t1中一列的引用。所以,MySQL看上去位于子查询的外部,并在外部查询中查æ‰�t1ã€�
假设è¡�t1包含一行,在此行中column1=5并且column2=6;同时,è¡�t2包含一行,在此行中column1=5并且column2=7。简单的表达å¼�... WHERE column1 = ANY (SELECT column1 FROM t2)会为TRUE。但是在本例中,在子查询中的WHERE子句ä¸�FALSE(因为(5ï¼�6)不等于ï¼�5ï¼�7)),所以子查询总体上为FALSEã€�
范围划分规则ï¼�MySQL从内到外进行评估。例如:
SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3
WHERE x.column2 = t3.column1));
在本语句中,x.column2必须是表t2中的列,因为SELECT column1 FROM t2 AS x ...å¯�t2进行了重命名。它不是è¡�t1中的列,因为SELECT column1 FROM t1 ...是一个更靠外的外部查诀€�
对于HAVINGæˆ�ORDER BY子句中的子查询,MySQL也会在外部选择清单中寻找列名称ã€�
对于特定的情况,相关联的子查询被优化。例如:
val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)
否则,这些子查询效率不高,可能速度会慢。把查询作为联合进行改写可能会改进效率ã€�
相关联的子查询不能从外部查询中引用总计函数的结果ã€�
åœ�SELECT语句çš�FROM子句中,子查询是合法的。实际的语法是:
SELECT ... FROM (subquery) [AS] name ...
[AS] name子句是强制性的,因ä¸�FROM子句中的每个表必须有一个名称。在子查询选择列表中的任何列都必须有唯一的名称。您可以在本手册中的其它地方找到对本语法的说明。在该处,所用的词语是“导出表”ã€�
为了进行详细说明,假设您有如下一个表ï¼�
CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
下面使用了示例表,解释了åœ�FROM子句中如何使用子查询ï¼�
INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
WHERE sb1 > 1;
结果ï¼�2, '2', 4.0ã€�
下面是另一个例子:假设您想了解一个分类后的表的一组和的平均值。采用如下操作:
SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;
不过,本查询提供所需的信息:
SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;
注意,在子查询中使用的列名称ï¼�sum_column1)被整理到外部查询中ã€�
FROM子句中的子查询可以返回标量、列、行或表ã€�FROM子句中的子查询不能为有关联的子查诀€�
即使å¯�EXPLAIN语句(即建立临时导出表)ï¼�FROM子句中的子查询也会被执行。这是因为在优化过程中,上一级的查询需要有关所有表的信息ã€�
以下错误只适用于子查询。本节把这些错误归在一起ã€�
· 来自子查询的列的数目不正ç¡�
· ERROR 1241 (ER_OPERAND_COL)
· SQLSTATE = 21000
· Message = "Operand should contain 1 column(s)"
在出现以下情况时,发生此错误ï¼�
SELECT (SELECT column1, column2 FROM t2) FROM t1;
如果您的目的是进行比较,您可以使用能返回多个列的子查诀€‚请参见13.2.8.5节,“行子查询â€�。不过,在其它的语境下,子查询必须为标量操作数ã€�
· 来自子查询的行的数目不正确:
· ERROR 1242 (ER_SUBSELECT_NO_1_ROW)
· SQLSTATE = 21000
· Message = "Subquery returns more than 1 row"
如果在语句中,子查询返回的行多于一个,则发生此错误。请考虑以下例子ï¼�
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
如果SELECT column1 FROM t2只返回一行,则将执行以前的查诀€‚如果子查询返回的行多于一个,则将出现错误1242。在这种情况下,该查询将被改写为ï¼�
SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);
· 在子查询中表格使用不正确ï¼�
· Error 1093 (ER_UPDATE_TABLE_USED)
· SQLSTATE = HY000
· Message = "You can't specify target table 'x'
· for update in FROM clause"
在如下情况下,发生该错误ï¼�
UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);
å’�SELECT语句一样,åœ�UPDATEå’�DELETE语句中,子查询是合法的。所以您可以åœ�UPDATE语句中使用子查询进行赋值。不过,您不能把同一个表(在本例中为è¡�t1)既用于子查询的FROM子句,又用于更新目标ã€�
对于事务存储引擎,子查询的错误会导致整个语句失效。对于非事务存储引擎,在遇到错误之前进行的数据修订会被保留ã€�
开发过程不断进展,所以从长远来看,没有一个可靠的优化技巧。有些技巧您可能会感兴趣,并原意采用ï¼�
· 有些子句会影响在子查询中的行的数量和顺序。使用这类子句。例如:
· SELECT * FROM t1 WHERE t1.column1 IN
· (SELECT column1 FROM t2 ORDER BY column1);
· SELECT * FROM t1 WHERE t1.column1 IN
· (SELECT DISTINCT column1 FROM t2);
· SELECT * FROM t1 WHERE EXISTS
· (SELECT * FROM t2 LIMIT 1);
· 用子查询替换联合。例如,试进行如下操作:
· SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
· SELECT column1 FROM t2);
代替如下操作ï¼�
SELECT DISTINCT t1.column1 FROM t1, t2
WHERE t1.column1 = t2.column1;
· 部分子查询可以被转换为联合,以便与不支持子查询的旧版本的MySQL相兼容。不过,在有些情况下,把子查询转化为联合可以提高效果。请参见13.2.8.11节,“把子查询作为用于早期MySQL版本的联合进行改写â€�ã€�
· 把子句从子查询的外部转移到内部。例如,使用此查询:
· SELECT * FROM t1
· WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
代替此查询:
SELECT * FROM t1
WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
另一个例子是,使用此查询ï¼�
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
代替此查询:
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
· 使用行子查询,代替关联子查询。举例说明,使用此查询:
· SELECT * FROM t1
· WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
代替此查询:
SELECT * FROM t1
WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
AND t2.column2=t1.column2);
· Use NOT (a = ANY (...)) rather than a <> ALL (...).
· Use x = ANY (table containing (1,2)) rather than x=1 OR x=2.
· Use = ANY rather than EXISTS.
· 对于只返回一行的无关联子查询ï¼�IN的速度慢于=。举例说明,使用此查询:
· SELECT * FROM t1 WHERE t1.col_name
· = (SELECT a FROM t2 WHERE b = some_const);
代替此查询:
SELECT * FROM t1 WHERE t1.col_name
IN (SELECT a FROM t2 WHERE b = some_const);
使用这些技巧可以使程序更快或更慀€‚使ç”�BENCHMARK()函数ç�MySQL工具,您可以了解到在您所处的情况下,哪些技巧会有帮助ã€�
MySQL本身进行的部分优化包括:
· MySQL只执行一次无关联子查诀€‚使ç”�EXPLAIN确认给定的子查询确实是无关联的ã€�
· MySQL改写IN, ALL, ANYå’�SOME子查询,目的是如果子查询中的select-list列已编制索引,则能发挥出此优势ã€�
· MySQL使用index-lookup函数代替以下格式的子查询ã€�EXPLAIN把此函数描述为特殊的联合类型ï¼�unique_subqueryæˆ�index_subquery):
· ... IN (SELECT indexed_column FROM single_table ...)
· 当表达式中不包含NULL值或空集时,MySQL使用一个包å��MIN()æˆ�MAX()的表达式,对以下格式的表达式进行扩展ï¼�
· value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)
例如,本WHERE子句ï¼�
WHERE 5 > ALL (SELECT x FROM t)
可以用优化符进行如下处理ï¼�
WHERE 5 > (SELECT MAX(x) FROM t)
åœ�MySQL内部手册中有一章名为â€�MySQL如何转换子查询”,可以ä»�http://dev.mysql.com/doc/获取ã€�
举例说明,本查询ï¼�
SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
可以被改写为ï¼�
SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;
以下查询ï¼�
SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);
也可以使ç”�IN()进行改写ï¼�
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
WHERE table2.id IS NULL;
LEFT [OUTER] JOIN可以比对应的子查询更快,因为服务器可能对其进行更好的优化——这一点对于单独的MySQL服务器并不明确。在SQL-92之前,不存在外部联合,因此在做某些事情时,子查询是唯一的方法。现在,MySQL服务器和其它许多先进的数据库系统都能提供多种的外部联合类型ã€�
MySQL支持multiple-table DELETE语句,该语句可以被用于高效地删除行。删除时依据来自一个表或同时来自多个表的信息。同时也支持Multiple-table UPDATE语句ã€�
TRUNCATE [TABLE] tbl_name
TRUNCATE TABLE用于完全清空一个表。从逻辑上说,该语句与用于删除所有行çš�DELETE语句等同,但是在有些情况下,两者在使用上有所不同ã€�
对于InnoDB表,如果有需要引用表的外键限制,åˆ�TRUNCATE TABLE被映射到DELETE上;否则使用快速删减(取消和重新创建表)。使ç”�TRUNCATE TABLE重新设置AUTO_INCREMENT计数器,设置时不考虑是否有外键限制ã€�
对于其它存储引擎,在MySQL 5.1中,TRUNCATE TABLEä¸�DELETE FROM有以下几处不同:
· 删减操作会取消并重新创建表,这比一行一行的删除行要快很多ã€�
· 删减操作不能保证对事务是安全的;在进行事务处理和表锁定的过程中尝试进行删减,会发生错误ã€�
· 被删除的行的数目没有被返回ã€�
· 只要表定义文ä»�tbl_name.frm是合法的,则可以使用TRUNCATE TABLE把表重新创建为一个空表,即使数据或索引文件已经被破坏ã€�
· 表管理程序不记得最后被使用çš�AUTO_INCREMENT值,但是会从头开始计数。即使对äº�MyISAMå’�InnoDB也是如此ã€�MyISAMå’�InnoDB通常不再次使用序列值ã€�
· 当被用于带分区的表时ï¼�TRUNCATE TABLE会保留分区;即,数据和索引文件被取消并重新创建,同时分区定义ï¼�.par)文件不受影响ã€�
TRUNCATE TABLE是在MySQL中采用的一ä¸�Oracle SQL扩展ã€�
Single-table语法ï¼�
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]
Multiple-table语法ï¼�
UPDATE [LOW_PRIORITY] [IGNORE] table_references
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
UPDATE语法可以用新值更新原有表行中的各列ã€�SET子句指示要修改哪些列和要给予哪些值ã€�WHERE子句指定应更新哪些行。如果没æœ�WHERE子句,则更新所有的行。如果指定了ORDER BY子句,则按照被指定的顺序对行进行更新ã€�LIMIT子句用于给定一个限值,限制可以被更新的行的数目ã€�
UPDATE语句支持以下修饰符:
· 如果您使ç”�LOW_PRIORITY关键词,åˆ�UPDATE的执行被延迟了,直到没有其它的客户端从表中读取为歀€�
· 如果您使ç”�IGNORE关键词,则即使在更新过程中出现错误,更新语句也不会中断。如果出现了重复关键字冲突,则这些行不会被更新。如果列被更新后,新值会导致数据转化错误,则这些行被更新为最接近的合法的值ã€�
如果您在一个表达式中通过tbl_name访问一列,åˆ�UPDATE使用列中的当前值。例如,以下语句把年龄列设置为比当前值多一ï¼�
mysql> UPDATE persondata SET age=age+1;
UPDATE赋值被从左到右评估。例如,以下语句对年龄列加倍,然后再进行增加:
mysql> UPDATE persondata SET age=age*2, age=age+1;
如果您把一列设置为其当前含有的值,åˆ�MySQL会注意到这一点,但不会更新ã€�
如果您把被已定义ä¸�NOT NULL的列更新ä¸�NULL,则该列被设置到与列类型对应的默认值,并且累加警告数。对于数字类型,默认值为0;对于字符串类型,默认值为空字符串('');对于日期和时间类型,默认值为â€�zero”值ã€�
UPDATE会返回实际被改变的行的数目ã€�Mysql_info() C API函数可以返回被匹配和被更新的行的数目,以及在UPDATE过程中产生的警告的数量ã€�
您可以使ç”�LIMIT row_count来限å®�UPDATE的范围ã€�LIMIT子句是一个与行匹配的限定。只要发现可以满è¶�WHERE子句çš�row_count行,则该语句中止,不论这些行是否被改变ã€�
如果一ä¸�UPDATE语句包括一ä¸�ORDER BY子句,则按照由子句指定的顺序更新行ã€�
您也可以执行包括多个表的UPDATE操作ã€�table_references子句列出了在联合中包含的表。该语法åœ�13.2.7.1节,“JOIN语法â€�中进行了说明。以下是一个例子:
UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;
以上的例子显示出了使用逗号操作符的内部联合,但æ˜�multiple-table UPDATE语句可以使用åœ�SELECT语句中允许的任何类型的联合,比如LEFT JOINã€�
注释:您不能æŠ�ORDER BYæˆ�LIMITä¸�multiple-table UPDATE同时使用ã€�
在一个被更改çš�multiple-table UPDATE中,有些列被引用。您只需要这些列çš�UPDATE权限。有些列被读取了,但是没被修改。您只需要这些列çš�SELECT权限ã€�
如果您使用的multiple-table UPDATE语句中包含带有外键限制的InnoDB表,åˆ�MySQL优化符处理表的顺序可能与上下层级关系的顺序不同。在此情况下,语句无效并è¢� 回滚。同时,更新一个单一表,并且依靠ON UPDATE功能。该功能ç”�InnoDB提供,用于对其它表进行相应的修改。请参见15.2.6.4节,“FOREIGN KEY约束â€�ã€�
目前,您不能在一个子查询中更新一个表,同时从同一个表中选择ã€�
{DESCRIBE | DESC} tbl_name [col_name | wild]
DESCRIBE可以提供有关表中各列的信息。它æ˜�SHOW COLUMNS FROM的快捷方式。这些语句也可以显示语句,用于阅览ã€�
è§�13.5.4.3节,“SHOW COLUMNS语法â€�ã€�
col_name可以是一个列名称,或一个包含‘%’和â€�_’的通配符的字符串,用于获得对于带有与字符串相匹配的名称的各列的输出。没有必要在引号中包含字符串,除非其中包含空格或其它特殊字符ã€�
mysql> DESCRIBE city;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| Id | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| Country | char(3) | NO | UNI | | |
| District | char(20) | YES | MUL | | |
| Population | int(11) | NO | | 0 | |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
NULL字段指示是否NULL可以被存储在列中ã€�
Key字段指示是否该列已编制索引ã€�PRI的值指示该列是表的主键的一部分ã€�UNI指示,该列是UNIQUE索引的一部分ã€�MUL值指示,在列中某个给定值多次出现是允许的ã€�
MUL将被显示åœ�UNIQUE索引中,原因之一是多个列会组合成一个复å��UNIQUE索引;尽管列的组合是唯一的,但每个列仍可以多次出现同一个给定值。注意,在复合索引中,只有索引最左边的列可以进入Key字段中ã€�
默认字段指示,默认值被赋予该列ã€�
Extra字段包含可以获取的与给定列有关的附加信息。在我们的例子中ï¼�Extra字段指示ï¼�Id列使ç”�AUTO_INCREMENT关键词创建ã€�
如果列类型与您预计的依据CREATE TABLE语句得出的列类型不同,则请注意,MySQL有时会改变列类型。请参见13.1.5.1节,“沉寂的列规格变更â€�ã€�
DESCRIBE语句被设立出来,用于ä¸�Oracle相兼容ã€�
SHOW CREATE TABLEå’�SHOW TABLE STATUS语句也可以提供有关表的信息。请参见13.5.4节,“SHOW语法â€�ã€�
USE db_name
USE db_name语句可以通告MySQLæŠ�db_name数据库作为默认(当前)数据库使用,用于后续语句。该数据库保持为默认数据库,直到语段的结尾,或者直到发布一个不同的USE语句ï¼�
mysql> USE db1;
mysql> SELECT COUNT(*) FROM mytable; # selects from db1.mytable
mysql> USE db2;
mysql> SELECT COUNT(*) FROM mytable; # selects from db2.mytable
使用USE语句为一个特定的当前的数据库做标记,不会阻碍您访问其它数据库中的表。下面的例子可以ä»�db1数据库访问作者表,并ä»�db2数据库访问编辑表ï¼�
mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
-> WHERE author.editor_id = db2.editor.editor_id;
USE语句被设立出来,用于ä¸�Sybase相兼容ã€�
MySQL通过SET AUTOCOMMIT, START TRANSACTION, COMMITå’�ROLLBACK等语句支持本地事务(在给定的客户端连接中)。请参见13.4.1节,“START TRANSACTION, COMMIT和ROLLBACK语法â€�ã€�XA事务支持还可以允è®�MySQL参与分布式事务。请参见13.4.7节,“XA事务â€�ã€�
START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}
START TRANSACTIONæˆ�BEGIN语句可以开始一项新的事务ã€�COMMIT可以提交当前事务,是变更成为永久变更ã€�ROLLBACK可以 回滚当前事务,取消其变更ã€�SET AUTOCOMMIT语句可以禁用或启用默认的autocommit模式,用于当前连接ã€�
自选的WORK关键词被支持,用äº�COMMITå’�RELEASE,与CHAINå’�RELEASE子句ã€�CHAINå’�RELEASE可以被用于对事务完成进行附加控制ã€�Completion_type系统变量的值决定了默认完成的性质。请参见5.3.3节,“服务器系统变量â€�ã€�
AND CHAIN子句会在当前事务结束时,立刻启动一个新事务,并且新事务与刚结束的事务有相同的隔离等级ã€�RELEASE子句在终止了当前事务后,会让服务器断开与当前客户端的连接。包å��NO关键词可以抑åˆ�CHAINæˆ�RELEASE完成。如æž�completion_type系统变量被设置为一定的值,使连锁或释放完成可以默认进行,此æ—�NO关键词有用ã€�
默认情况下,MySQL采用autocommit模式运行。这意味着,当您执行一个用于更新(修改)表的语句之后,MySQL立刻把更新存储到磁盘中ã€�
如果您正在使用一个事务安全型的存储引擎(å¦�InnoDB, BDBæˆ�NDB簇),则您可以使用以下语句禁ç”�autocommit模式ï¼�
SET AUTOCOMMIT=0;
通过æŠ�AUTOCOMMIT变量设置为零,禁ç”�autocommit模式之后,您必须使用COMMIT把变更存储到磁盘中,或着如果您想要忽略从事务开始进行以来做出的变更,使ç”�ROLLBACKã€�
如果您想要对于一个单一系列的语句禁ç”�autocommit模式,则您可以使ç”�START TRANSACTION语句ï¼�
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;
使用START TRANSACTIONï¼�autocommit仍然被禁用,直到您使ç”�COMMITæˆ�ROLLBACK结束事务为止。然å��autocommit模式恢复到原来的状态ã€�
BEGINå’�BEGIN WORK被作ä¸�START TRANSACTION的别名受到支持,用于对事务进行初始化ã€�START TRANSACTION是标准的SQL语法,并且是启动一ä¸�ad-hoc事务的推荐方法ã€�BEGIN语句ä¸�BEGIN关键词的使用不同ã€�BEGIN关键词可以启动一ä¸�BEGIN...END复合语句。后者不会开始一项事务。请参见20.2.7节,“BEGIN ... END复合语句â€�ã€�
您也可以按照如下方法开始一项事务:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
WITH CONSISTENT SNAPSHOT子句用于启动一个一致的读取,用于具有此类功能的存储引擎。目前,该子句只适用äº�InnoDB。该子句的效果与发布一ä¸�START TRANSACTION,后面跟一个来自任ä½�InnoDB表的SELECT的效果一样。请参见15.2.10.4节,“一致的非锁定读â€�ã€�
开始一项事务会造成一个隐含的UNLOCK TABLES被执行ã€�
为了获得最好的结果,事务应只使用由单一事务存储引擎管理的表执行。否则,会出现以下问题:
· 如果您使用的表来自多个事务安全型存储引擎(例å¦�InnoDBå’�BDB),并且事务隔离等级不是SERIALIZABLE,则有可能当一个事务提交时,其它正在进行中的、使用同样的表的事务将只会发生由第一个事务产生的变更。也就是,用混合引擎不能保证事务的原子性,并会造成不一致。(如果混合引擎事务不经常有,则您可以根据需要使ç”�SET TRANSACTION ISOLATION LEVEL把隔离等级设置到SERIALIZABLE。)
· 如果您在事务中使用非事务安全型表,则对这些表的任何变更被立刻存储,不è®�autocommit模式的状态如何ã€�
如果您在更新了事务中一个事务表之后,发布一ä¸�ROLLBACK语句,则会出现一ä¸�ER_WARNING_NOT_COMPLETE_ROLLBACK警告。对事务安全型表的变更被 回滚,但是对非事务安全型表没有变更ã€�
每个事务被存储在一个组块中的二进制日志中,åœ�COMMIT之上。被回滚的事务不被计入日志。(例外情况:对非事务表的更改不会被 回滚。如果一个被回滚的事务包括对非事务表的更改,则整个事务使用一个在末端çš�ROLLBACK语句计入日志,以确保对这些表的更改进行复制。)è§�5.11.3节,“二进制日志â€�ã€�
您可以使ç”�SET TRANSACTION ISOLATION LEVEL更改事务的隔离等级。请参见13.4.6节,“SET TRANSACTION语法â€�ã€�
回滚可以慢速运行。在用户没有明确要求时,也可以进行回滚(例如,当错误发生时)。因此,在明确地和隐含的ï¼�ROLLBACK SQL命令)回滚时ï¼�SHOW PROCESSLIST会在Stage列中显示Rolling back,用于连接ã€�
有些语句不能被回滚。通常,这些语句包括数据定义语言ï¼�DDL)语句,比如创建或取消数据库的语句,和创建、取消或更改表或存储的子程序的语句ã€�
您在设计事务时,不应包含这类语句。如果您在事务的前部中发布了一个不能被回滚的语句,则后部的其它语句会发生错误,在这些情况下,通过发布ROLLBACK语句不能 回滚事务的全部效果ã€�
以下语句(以及同义词)均隐含地结束一个事务,似乎是在执行本语句前,您已经进行了一ä¸�COMMITã€�
· ALTER FUNCTION, ALTER PROCEDURE, ALTER TABLE, BEGIN, CREATE DATABASE, CREATE FUNCTION, CREATE INDEX, CREATE PROCEDURE, CREATE TABLE, DROP DATABASE, DROP FUNCTION, DROP INDEX, DROP PROCEDURE, DROP TABLE, LOAD MASTER DATA, LOCK TABLES, RENAME TABLE, SET AUTOCOMMIT=1, START TRANSACTION, TRUNCATE TABLE, UNLOCK TABLES.
· 当当前所有的表均被锁定时ï¼�UNLOCK TABLES可以提交事务ã€�
· CREATE TABLE, CREATE DATABASE DROP DATABASE, TRUNCATE TABLE, ALTER FUNCTION, ALTER PROCEDURE, CREATE FUNCTION, CREATE PROCEDURE, DROP FUNCTIONå’�DROP PROCEDURE等语句会导致一个隐含提交ã€�
· InnoDB中的CREATE TABLE语句被作为一个单一事务进行处理。这意味着,来自用户的ROLLBACK不会撤销用户在事务处理过程中创建çš�CREATE TABLE语句ã€�
事务不能被嵌套。这是隐å��COMMIT的结果。当您发布一ä¸�START TRANSACTION语句或其同义词时,该COMMIT被执行,用于任何当前事务ã€�
SAVEPOINT identifier
ROLLBACK [WORK] TO SAVEPOINT identifier
RELEASE SAVEPOINT identifier
InnoDB支持SQL语句SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT和自选的用于ROLLBACKçš�WORK关键词ã€�
SAVEPOINT语句用于设置一个事务保存点,带一个标识符名称。如果当前事务有一个同样名称的保存点,则旧的保存点被删除,新的保存点被设置ã€�
ROLLBACK TO SAVEPOINT语句会向以命名的保存点回滚一个事务。如果在保存点被设置后,当前事务对行进行了更改,则这些更改会åœ� 回滚中被撤销。但是,InnoDB不会释放被存储在保存点之后的存储器中的行锁定。(注意,对于新插入的行,锁定信息被存储在行中的事务ID承载;锁定没有被分开存储在存储器中。在这种情况下,行锁定在撤销中被释放。)在被命名的保存点之后设置的保存点被删除ã€�
如果语句返回以下错误,则意味着不存在带有指定名称的保存点:
ERROR 1181: Got error 153 during ROLLBACK
RELEASE SAVEPOINT语句会从当前事务的一组保存点中删除已命名的保存点。不出现提交æˆ� 回滚。如果保存点不存在,会出现错误ã€�
如果您执è¡�COMMIT或执行不能命名保存点çš�ROLLBACK,则当前事务的所有保存点被删除ã€�
LOCK TABLES
tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...
UNLOCK TABLES
LOCK TABLES可以锁定用于当前线程的表。如果表被其它线程锁定,则造成堵塞,直到可以获取所有锁定为歀€�UNLOCK TABLES可以释放被当前线程保持的任何锁定。当线程发布另一ä¸�LOCK TABLES时,或当与服务器的连接被关闭时,所有由当前线程锁定的表被隐含地解锁ã€�
表锁定只用于防止其它客户端进行不正当地读取和写入。保持锁定(即使是读取锁定)的客户端可以进行表层级的操作,比å¦�DROP TABLEã€�
注意,下面是对事务表使用LOCK TABLES的说明:
· 在尝试锁定表之前ï¼�LOCK TABLES不是事务安全型的,会隐含地提交所有活性事务。同时,开始一项事务(例如,使ç”�START TRANSACTION),会隐含地执行UNLOCK TABLES。(è§�13.4.3节,“会造成隐式提交的语句â€�ã€�
· 对事务表(如InnoDB)使ç”�LOCK TABLES的正确方法是,设ç½�AUTOCOMMIT=0并且不能调用UNLOCK TABLES,直到您明确地提交事务为歀€‚当您调ç”�LOCK TABLES时,InnoDB会内部地取其自己的表锁定ï¼�MySQL取其自己的表锁定ã€�InnoDB在下一个提交时释放其表锁定,但是,对于MySQL,要释放表锁定,您必须调ç”�UNLOCK TABLES。您不应该让AUTOCOMMIT=1,因为那样的话,InnoDB会在调用LOCK TABLES之后立刻释放表锁定,并且很容易形成死锁定。注意,如果AUTOCOMMIT=1,我们根本不能获å��InnoDB表锁定,这样就可以帮助旧的应用软件避免不必要的死锁定ã€�
· ROLLBACK不会释放MySQL的非事务表锁定ã€�
要使ç”�LOCK TABLES,您必须拥有相关表的LOCK TABLES权限å’�SELECT权限ã€�
使用LOCK TABLES的主要原因是仿效事务,或在更新表时加快速度。这将在后面进行更详细的解释ã€�
如果一个线程获得对一个表åœ�READ锁定,该线程(和所有其它线程)只能从该表中读取。如果一个线程获得对一个表çš�WRITE锁定,只有保持锁定的线程可以对表进行写入。其它的线程被阻止,直到锁定被释放时为止ã€�
READ LOCALå’�READ之间的区别是ï¼�READ LOCAL允许在锁定被保持时,执行非冲突æ€�INSERT语句(同时插入)。但是,如果您正打算åœ�MySQL外面操作数据库文件,同时您保持锁定,则不能使ç”�READ LOCAL。对äº�InnoDB表,READ LOCALä¸�READ相同ã€�
当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。虽然使ç”�LOCK TABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,在此情况下,您必须分别获得对每个别名的锁定ã€�
mysql> LOCK TABLE t WRITE, t AS t1 WRITE;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;
如果您的查询使用一个别名引用一个表,那么您必须使用同样的别名锁定该表。如果没有指定别名,则不会锁定该表ã€�
mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
相反的,如果您使用一个别名锁定一个表,您必须使用该别名在您的查询中引用该表ã€�
mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;
WRITE锁定通常æ¯�READ锁定拥有更高的优先权,以确保更新被尽快地处理。这意味着,如果一个线程获得了一ä¸�READ锁定,则另一个线程会申请一ä¸�WRITE锁定,后续的READ锁定申请会等待,直到WRITE线程获得锁定并释放锁定。您可以使用LOW_PRIORITY WRITE锁定来允许其它线程在该线程正在等å¾�WRITE锁定时获å¾�READ锁定。只有当您确定最终将有一个时机,此时没有线程拥有READ锁定时,您才应该使用LOW_PRIORITY WRITE锁定ã€�
LOCK TABLES按照如下方式执行ï¼�
1. 按照内部定义的顺序,对所有要被锁定的表进行分类。从用户的角度,此顺序是未经定义的ã€�
2. 如果使用一个读取和一个写入锁定对一个表进行锁定,则把写入锁定放在读取锁定之前ã€�
3. 一次锁定一个表,直到线程得到所有锁定为歀€�
该规则确保表锁定不会出现死锁定。但是,对于该规则,您需要注意其它的事情ï¼�
如果您正在对一个表使用一ä¸�LOW_PRIORITY WRITE锁定,这只意味着ï¼�MySQL等待特定的锁定,直到没有申请READ锁定的线程时为止。当线程已经获得WRITE锁定,并正在等待得到锁定表清单中的用于下一个表的锁定时,所有其它线程会等待WRITE锁定被释放。如果这成为对于应用程序的严重的问题,则您应该考虑把部分表转化为事务安全型表ã€�
您可以安全地使用KILL来结束一个正在等待表锁定的线程。请参见13.5.5.3节,“KILL语法â€�ã€�
注意,您不能使用INSERT DELAYED锁定任何您正在使用的表,因为,在这种情况下,INSERT由另一个线程执行ã€�
通常,您不需要锁定表,因为所有的单个UPDATE语句都是原子性的;没有其它的线程可以干扰任何其它当前正在执行çš�SQL语句。但是,在几种情况下,锁定表会有好处ï¼�
· 如果您正在对一ç»�MyISAM表运行许多操作,锁定您正在使用的表,可以快很多。锁å®�MyISAM表可以加快插入、更新或删除的速度。不利方面是,没有线程可以更新一个用READ锁定的表(包括保持锁定的表),也没有线程可以访问ç”�WRITE锁定的表(除了保持锁定的表以外)ã€�
有些MyISAM操作åœ�LOCK TABLES之下更快的原因是ï¼�MySQL不会清空用于已锁定表的关键缓存,直到UNLOCK TABLE被调用为歀€‚通常,关键缓存在每个SQL语句之后被清空ã€�
· 如果您正在使ç”�MySQL中的一个不支持事务的存储引擎,则如果您想要确定åœ�SELECTå’�UPDATE之间没有其它线程,您必须使用LOCK TABLES。本处所示的例子要求LOCK TABLES,以便安全地执行ï¼�
· mysql> LOCK TABLES trans READ, customer WRITE;
· mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
· mysql> UPDATE customer
· -> SET total_value=sum_from_previous_statement
· -> WHERE customer_id=some_id;
· mysql> UNLOCK TABLES;
如果没有LOCK TABLES,有可能另一个线程会在执è¡�SELECTå’�UPDATE语句之间åœ�trans表中插入一个新行ã€�
通过使用相对更新ï¼�UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函数,您可以在许多情况下避免使用LOCK TABLES。请参见1.8.5.3节,“事务和原子操作â€�ã€�
通过使用用户层级的顾问式锁定函数GET_LOCK()å’�RELEASE_LOCK(),您也可以在有些情况下避免锁定表。这些锁定被保存在服务器中的一个混编表中,使用pthread_mutex_lock() å’�pthread_mutex_unlock(),以加快速度。请参见12.9.4节,“其他函数â€�ã€�
要了解更多有关锁定规则的说明,请参见7.3.1节,“锁定方法â€�ã€�
您可以使ç”�FLUSH TABLES WITH READ LOCK语句锁定位于所有带有读取锁定的数据库中的所有表。请参见13.5.5.2节,“FLUSH语法â€�。如果您有一个可以及时拍摄快照的文件系统,比å¦�Veritas,这是获得备份的一个非常方便的方式ã€�
注释:如果您对一个已锁定的表使用ALTER TABLE,该表可能会解锁。请参见A.7.1节,“与ALTER TABLE有关的问题â€�ã€�
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
本语句用于设置事务隔离等级,用于下一个事务,或者用于当前会话ã€�
在默认情况下ï¼�SET TRANSACTION会为下一个事务(还未开始)设置隔离等级。如果您使用GLOBAL关键词,则语句会设置全局性的默认事务等级,用于从该点以后创建的所有新连接。原有的连接不受影响。要进行此操作,您需è¦�SUPER权限。使ç”�SESSION关键测可以设置默认事务等级,用于对当前连接执行的所有将来事务ã€�
要了解对每个InnoDB事务隔离等级的描述,请参è§�15.2.10.3节,“InnoDB和TRANSACTION ISOLATION LEVELâ€�ã€�InnoDB支持MySQL 5.1中的各个等级。默认的等级æ˜�REPEATABLE READã€�
您可以使ç”�--transaction-isolation选项,对mysqld设置初始的默认全局隔离等级。请参见5.3.1节,â€�mysqld命令行选项â€�ã€�
对于InnoDB存储引擎,可以获得对XA事务的支持ã€�MySQL XA的执行依æ��X/Open CAE文件Distributed Transaction Processing: The XA Specification。本文件ç”�Open Group出版,可以从http://www.opengroup.org/public/pubs/catalog/c193.htm获取。在I.5节,“对XA事务的限制â€�对当å‰�XA执行的限制进行了描述ã€�
在客户端方面,没有特殊要求。连æŽ�MySQL服务器的XA接口由以XA关键词开头的SQL语句组成ã€�MySQL客户端必须能发é€�SQL语句,并能理è§�XA语句接口的语义,但是它们不需要被链接到特定的MySQL客户库上ã€�
当前,在MySQL连接器当中,MySQL连接å™�/J 5.0.0直接支持XA(也就是,通过一个可以控åˆ�XA SQL语句接口的等级接口)ã€�
XA支持分布式的事务,具备能力,让多个独立的事务资源参加全局的事务。事务资源通常æ˜�RDBMSs,不过也可以是其它种类的资源ã€�
一个全局事务会涉及到多个行动,这些行动本身是事务性的。不过,所有行动都必须作为一个群组成功完成,或者作为一个群组被回滚。实际上,这会延ä¼�ACID性质,“提高等级”,这样,多ä¸�ACID事务就可以一起执行,相当于也拥有ACID性质的全局操作的组件。(但是,对于一个分布式事务,您必须使用SERAILIZABLE隔离等级,以实现ACID性质。对于一个非分布式事务,使用REPEATABLE READ就足够了。但是对于分布式事务,使ç”�REPEATABLE READ是不够的。)
分布式事务的部分示例ï¼�
· 应用程序相当于一个把消息传递服务和RDBMS组合在一起的整合工具。应用程序可以确保,所有进行消息发送、回收和处理的事务(同时包含一个事务数据库)均在一个全局事务中发生。您可以把这看作是“事务电子邮件。â€�
· 应用程序执行的行动会涉及到不同数据库服务器,比如MySQL服务器和Oracle服务器(或多ä¸�MySQL服务器)。涉及到多个服务器的行动必须作为一个全局事务的一部分发生,而不是作为针对每个服务器的独立的本地事务发生ã€�
· 银行把帐户信息保存在RDBMS中,并通过自动取款机(ATMs)分发和收取欠款。必须要确保ATM行动被正确地反映到帐户中,但是这不能只由RDBMS单独完成。全局事务管理器会整合ATM和数据库资源,以确保财务事务的整体一致性ã€�
使用全局事务的应用程序涉及一个或多个资源管理器和一个事务管理器ï¼�
· 资源管理器(RM)用于提供通向事务资源的途径。数据库服务器是一种资源管理器。该管理器必须可以提交或 回滚ç”�RM管理的事务ã€�
· 事务管理器(TM)用于协调作为一个全局事务一部分的事务ã€�TM与管理每个事务的RMs进行通讯。一个全局事务中各个单个事务均是全局事务的“分支”。全局事务和各分支通过一种命名方法进行标识。这种命名方法在后面进行讲述ã€�
MySQL执行XA MySQL时,MySQL服务器相当于一个用于管理全局事务中的XA事务的资源管理器。与MySQL服务器连接的客户端相当于事务管理器ã€�
要执行一个全局事务,必须知道涉及到了哪些组件,并且把每个组件引到一点,在此时,组件可以被提交或回滚时。根据每个组件报告的有关组件效能的内容,这些组件必须作为一个原子性群组全部提交或 回滚。即,要么所有的组件必须提交,要么所有的组件必须回滚。要管理一个全局事务,必须要考虑任何组件或连接网络可能会故障ã€�
用于执行全局事务的过程使用两阶段提交ï¼�2PC),发生时间在由全局事务的分支进行的行动已经被执行之后ã€�
1. 在第一阶段,所有的分支被预备好。即,它们被TM告知要准备提交。通常,这意味着用于管理分支的每ä¸�RM会记录对于被稳定保存的分支的行动。分支指示是否它们可以这么做。这些结果被用于第二阶段ã€�
2. 在第二阶段,TM告知RMs是否要提交或 回滚。如果在预备分支时,所有的分支指示它们将能够提交,则所有的分支被告知要提交。如果在预备时,有任何分支指示它将不能提交,则所有分支被告知 回滚ã€�
在有些情况下,一个全局事务可能会使用一阶段提交ï¼�1PC)。例如,当一个事务管理器发现,一个全局事务只由一个事务资源组成(即,单一分支),则该资源可以被告知同时进行预备和提交ã€�
要在MySQL中执è¡�XA事务,应使用以下语句ï¼�
XA {START|BEGIN} xid [JOIN|RESUME]
XA END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid
XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid
XA RECOVER
对于XA STARTï¼�JOINå’�RESUME子句不被支持ã€�
对于XA ENDï¼�SUSPEND [FOR MIGRATE]子句不被支持ã€�
每个XA语句ä»�XA关键词为开头,多数语句要求一ä¸�xid值ã€� xid是一ä¸�XA事务标识符。它指示该语句适用于哪个事务ã€�xid值由客户端提供,或由MySQL服务器生成ã€�xid值包含一到三个部分:
xid: gtrid [, bqual [, formatID ]]
gtrid是一个全局事务标识符,bqual是一个分支限定符ï¼�formatID是一个数字,用于标识ç”�gtridå’�bqual值使用的格式。根据语法的表示ï¼�bqualå’�formatID是自选的。如果没有给定,默认çš�bqual值是''。如果没有给定,默认çš�fromatID值是1ã€�
gtridå’�bqual必须为字符串文字,每个的长度最多为64字节(不是字符)ã€�gtridå’�bqual可以用多种方法指定。您可以使用带引号的字符ä¸�('ab'),十六进制字符串(0x6162, X'ab'),或位å€�(b'nnnn')ã€�
formatID是一个无符号的整数ã€�
通过MySQL服务器的带下划线çš�XA支持子程序,gtridå’�bqual值被理解为以字节为单位。但是,在包å��XA语句çš�SQL语句正在被分析的同时,服务器会去操作一些特定的字符集。为了安全,æŠ�gtridå’�bqual作为十六进制字符串写入ã€�
通常ï¼�xid值由事务管理器生成。由一ä¸�TM生成的值必须与由其å®�TMs生成的值不同。一个给定的TM必须能识别自己的xid值。这些值位于由XA RECOVER语句返回的值清单中ã€�
XA START xid用于启动一个带给定xid值的XA事务。每ä¸�XA事务必须有一个唯一çš�xid值,因此该值当前不能被其它çš�XA事务使用。使ç”�gtridå’�bqual值评估唯一性。所有下列的用于XA事务çš�XA语句必须使用ä¸�XA START语句中给定的相同çš�xid值进行指定。如果您使用这些语句,但是指定的xid值与部分原有çš�XA事务不对应的话,会发生错误ã€�
一项或多项XA事务可以是同一个全局事务的一部分。在一个给定的全局事务中的所æœ�XA事务必须åœ�xid值中使用同样çš�gtrid值。出于这个原因,gtrid值必须为全局唯一的,这样,有关一个给定的XA事务是哪个全局事务的一部分的问题就不会含糊不清。对于一个全局事务中的每个XA事务ï¼�xid值中çš�bqual部分必须不一样。(bqual值应不一样,这个要求是当前执è¡�MySQL XA的一个限制条件。这不是XA规约的一部分。)
对于åœ�MySQL服务器上的处äº�PREPARED状态的XA事务ï¼�XA RECOVER语句会返回信息。(è§�13.4.7.2节,“XA事务状态â€�.。)输出包括一个行,该行用于服务器上的每个这类XA事务,不论是哪个客户端启动了它ã€�
XA RECOVER输出行看上去像这样(例如ï¼�xid值包æ‹�'abc', 'def'å’� 7等部分)ï¼�
mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 7 | 3 | 3 | abcdef |
+----------+--------------+--------------+--------+
输出列有以下意义ï¼�
· formatID是事åŠ�xidçš�formatID部分
· gtrid_lengthæ˜�xidçš�gtrid部分的长度,以字节为单位
· bqual_lengthæ˜�xidçš�bqual部分的长度,以字节为单位
· dataæ˜�xidçš�gtrid部分å’�bqual部分的串è��
1. 使用XA START来启动一ä¸�XA事务,并把它放入ACTIVE状态ã€�
2. 对于一ä¸�ACTIVE XA事务,发布构成事务的SQL语句,然后发布一ä¸�XA END语句ã€�XA END把事务放å…�IDLE状态ã€�
3. 对于一ä¸�IDLE XA事务,您可以发布一ä¸�XA PREPARE语句或一ä¸�XA COMMITâ€�ONE PHASE语句ï¼�
· XA PREPARE把事务放å…�PREPARED状态。在此点上的XA RECOVER语句将在其输出中包括事务çš�xid值,因为XA RECOVER会列出处äº�PREPARED状态的所æœ�XA事务ã€�
· XA COMMITâ€�ONE PHASE用于预备和提交事务ã€�xid值将不会è¢�XA RECOVER列出,因为事务终歀€�
4. 对于一ä¸�PREPARED XA事务,您可以发布一ä¸�XA COMMIT语句来提交和终止事务,或者发å¸�XA ROLLBACK来回滚并终止事务ã€�
下面是一个简单的XA事务,该事务把一行作为一个全局事务的一部分插入一个表中ã€�
mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)
mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
根据一个给定的客户端连接的语境ï¼�XA事务和本地(é��XA)事务互相排斥。举例说明,如果已经发布äº�XA START来开始一é¡�XA事务,则本地事务不会被启动,直到XA事务已经被提交或è¢� 回滚为止。相反的,如果已经使ç”�START TRANSACTION启动一个本地事务,åˆ�XA语句不能被使用,直到该事务被提交或被 回滚为止ã€�
CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] ...
CREATE USER用于创建新的MySQL账户。要使用CREATE USER,您必须拥有mysql数据库的全局CREATE USER权限,或拥有INSERT权限。对于每个账户,CREATE USER会在没有权限çš�mysql.user表中创建一个新记录。如æž� 账户已经存在,则出现错误ã€�
使用自选的IDENTIFIED BY子句,可以为账户给定一个密码ã€�user值和 密码的给定方法和GRANT语句一样。特别是,要在纯文本中指定密码,需忽略PASSWORD关键词。要æŠ� 密码指定为由PASSWORD()函数返回的混编值,需包含关键å�PASSWORD。请参见13.5.1.3节,“GRANT和REVOKE语法â€�ã€�
DROP USER user [, user] ...
DROP USER语句用于删除一个或多个MySQL账户。要使用DROP USER,您必须拥有mysql数据库的全局CREATE USER权限æˆ�DELETE权限。使用与GRANTæˆ�REVOKE相同的格式为每个 账户命名;例如,'jeffrey'@'localhost'ã€� 账户名称的用户和主机部分与用户表记录çš�Userå’�Host列值相对应ã€�
使用DROP USER,您可以取消一个账户和其权限,操作如下ï¼�
DROP USER user;
该语句可以删除来自所有授权表的帐户权限记录ã€�
要点ï¼�DROP USER不能自动关闭任何打开的用户对话。而且,如果用户有打开的对话,此时取消用户,则命令不会生效,直到用户对话被关闭后才生效。一旦对话被关闭,用户也被取消,此用户再次试图登录时将会失败。这是有意设计的ã€�
GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON [object_type] {tbl_name | * | *.* | db_name.*}
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] ...
[REQUIRE
NONE |
[{SSL| X509}]
[CIPHER 'cipher' [AND]]
[ISSUER 'issuer' [AND]]
[SUBJECT 'subject']]
[WITH with_option [with_option] ...]
object_type =
TABLE
| FUNCTION
| PROCEDURE
with_option =
GRANT OPTION
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON [object_type] {tbl_name | * | *.* | db_name.*}
FROM user [, user] ...
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...
GRANTå’�REVOKE语句允许系统管理员创å»�MySQL用户 账户,授予权限和撤销权限ã€�
MySQL账户信息存储åœ�mysql数据库的表中。在ç¬�5章:数据库管ç��中对本数据库和访问控制系统进行了详尽的讨论。要了解更多详细信息,您应该查询此章ã€�
如果授权表拥有含æœ�mixed-case数据库或表名称的权限记录,并ä¸�lower_case_table_names系统变量已设置,则不能使ç”�REVOKE撤销权限,必须直接操纵授权表。(å½�lower_case_table_names已设置时ï¼�GRANT将不会创建此类记录,但是此类记录可能已经在设置变量之前被创建了。)
授予的权限可以分为多个层级:
· 全局层级
全局权限适用于一个给定服务器中的所有数据库。这些权限存储在mysql.user表中ã€�GRANT ALL ON *.*å’�REVOKE ALL ON *.*只授予和撤销全局权限ã€�
· 数据库层çº�
数据库权限适用于一个给定数据库中的所有目标。这些权限存储在mysql.dbå’�mysql.host表中ã€�GRANT ALL ON db_name.*å’�REVOKE ALL ON db_name.*只授予和撤销数据库权限ã€�
· 表层çº�
表权限适用于一个给定表中的所有列。这些权限存储在mysql.talbes_priv表中ã€�GRANT ALL ON db_name.tbl_nameå’�REVOKE ALL ON db_name.tbl_name只授予和撤销表权限ã€�
· 列层çº�
列权限适用于一个给定表中的单一列。这些权限存储在mysql.columns_priv表中。当使用REVOKE时,您必须指定与被授权列相同的列ã€�
· 子程序层çº�
CREATE ROUTINE, ALTER ROUTINE, EXECUTEå’�GRANT权限适用于已存储的子程序。这些权限可以被授予为全局层级和数据库层级。而且,除äº�CREATE ROUTINE外,这些权限可以被授予为子程序层级,并存储在mysql.procs_priv表中ã€�
当后续目标是一个表、一个已存储的函数或一个已存储的过程时ï¼�object_type子句应被指定ä¸�TABLEã€�FUNCTIONæˆ�PROCEDURE。当从旧版本çš�MySQL升级时,要使用本子句,您必须升级您的授权表。请参见2.10.2节,“升级授权表â€�ã€�
要使ç”�GRANTæˆ�REVOKE,您必须拥有GRANT OPTION权限,并且您必须用于您正在授予或撤销的权限ã€�
要撤销所有权限,需使用以下语法。此语法用于取消对于已命名的用户的所有全局层级、数据库层级、表层级和列层级的权限ã€�
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...
要使用本REVOKE语法,您必须拥有mysql数据库的全局CREATE USER权限æˆ�UPDATE权限ã€�
对于GRANTå’�REVOKE语句ï¼�priv_type可以被指定为以下任何一种:
|
权限 |
意义 |
|
ALL [PRIVILEGES] |
设置é™�GRANT OPTION之外的所有简单权é™� |
|
ALTER |
允许使用ALTER TABLE |
|
ALTER ROUTINE |
更改或取消已存储的子程序 |
|
CREATE |
允许使用CREATE TABLE |
|
CREATE ROUTINE |
创建已存储的子程åº� |
|
CREATE TEMPORARY TABLES |
允许使用CREATE TEMPORARY TABLE |
|
CREATE USER |
允许使用CREATE USER, DROP USER, RENAME USERå’�REVOKE ALL PRIVILEGESã€� |
|
CREATE VIEW |
允许使用CREATE VIEW |
|
DELETE |
允许使用DELETE |
|
DROP |
允许使用DROP TABLE |
|
EXECUTE |
允许用户运行已存储的子程åº� |
|
FILE |
允许使用SELECT...INTO OUTFILEå’�LOAD DATA INFILE |
|
INDEX |
允许使用CREATE INDEXå’�DROP INDEX |
|
INSERT |
允许使用INSERT |
|
LOCK TABLES |
允许对您拥有SELECT权限的表使用LOCK TABLES |
|
PROCESS |
允许使用SHOW FULL PROCESSLIST |
|
REFERENCES |
未被实施 |
|
RELOAD |
允许使用FLUSH |
|
REPLICATION CLIENT |
允许用户询问从属服务器或主服务器的地址 |
|
REPLICATION SLAVE |
用于复制型从属服务器(从主服务器中读取二进制日志事件ï¼� |
|
SELECT |
允许使用SELECT |
|
SHOW DATABASES |
SHOW DATABASES显示所有数据库 |
|
SHOW VIEW |
允许使用SHOW CREATE VIEW |
|
SHUTDOWN |
允许使用mysqladmin shutdown |
|
SUPER |
允许使用CHANGE MASTER, KILL, PURGE MASTER LOGSå’�SET GLOBAL语句ï¼�mysqladmin debug命令;允许您连接(一次),即使已达到max_connectionsã€� |
|
UPDATE |
允许使用UPDATE |
|
USAGE |
“无权限”的同义è¯� |
|
GRANT OPTION |
允许授予权限 |
当从旧版本的MySQL升级时,要使ç”�EXECUTE, CREATE VIEW, SHOW VIEW, CREATE USER, CREATE ROUTINEå’�ALTER ROUTINE权限,您必须首先升级您的授权表。请参见2.10.2节,“升级授权表â€�ã€�
REFERENCES权限目前未被使用ã€�
当您想要创建一个没有权限的用户时,可以指定USAGEã€�
使用SHOW GRANTS来确定帐户拥有什么权限。请参见13.5.4.10节,“SHOW GRANTS语法â€�ã€�
您可以通过使用ON *.*语法赋予全局权限,或通过使用ON db_name.*语法赋予数据库层级权限。如果您指定äº�ON *并且您已经选择了一个默认数据库,则权限被赋予到这个数据库中。(警告:如果您指定äº�ON *同时您没有选择一个默认数据库,则权限是全局的。)
FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWNå’�SUPER权限是管理性权限,只能进行全局授权(使ç”�ON *.*语法)ã€�
其它权限可以被全局授权,或被赋予为其它层级ã€�
对于一个表,您可以指定çš�priv_type值只能是SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT OPTION, INDEXå’�ALTERã€�
对于一个列(也就是,当您使用一ä¸�column_list子句时),您可以指定çš�priv_type值只能是SELECT, INSERTå’�UPDATEã€�
在子程序层级,您可以指定çš�priv_type值只能是ALTER ROUTINE, EXECUTEå’�GRANT OPTIONã€�CREATE ROUTINE不是一个子程序层级的权限,因为您必须拥有此权限,才能创建一个子程序ã€�
对于全局、数据库、表和子程序层级ï¼�GRANT ALL只能赋予在您正在授权的层级中存在的权限。例如,如果您使ç”�GRANT ALL ON db_name.*,这是一个数据库层级语句,因此不会授予全局权限,如FILE等ã€�
MySQL允许您对不存在的数据库目标授予权限。在此情况下,将被授予的权限必须包括CREATE权限。这个性质是有意设计的,目的是允许数据库管理员为将在此后被创建的数据库目标预备用户 账户和权限ã€�
要点:当您取消一个表或数据库时,MySQL不会自动撤销任何权限。但是,如果您取消一个子程序,则被赋予该子程序的所有子程序层级的权限都被撤销ã€�
注意ï¼�GRANT语句用于在全局层级或数据库层级赋予权限。当åœ�GRANT语句中指定数据库名称时,允许使用â€�_’和â€�%’通配符。这意味着,如果您想要使用â€�_’字符作为一个数据库名称的一部分,您应该åœ�GRANT语句中指定它为â€�\_’,以防止用户可以访问其它符合此通配符格式的数据库;例如ï¼�GRANT ... ON `foo\_bar`.* TO ...ã€�
为了接纳对来自任意主机的用户授权的权利,MySQL支持ä»�user_name@host_name的形式指å®�user值。如果一ä¸�user_nameæˆ�host_name与一个不加引号的标识符一样是合法的,那么您不需要对它加引号。不过,要指定一个包含特殊字符(如â€�-’)çš�user_name字符串,或一个包含特殊字符或通配字符(如â€�%’),则引号是必要的;例如,'test-user'@'test-hostname'。分别对usernameå’�hostname加引号ã€�
您可以在hostname中指定通配符。例å¦�user_name@'%.loc.gov'适用于在loc.gov域中的任何主机的user_name。同æ—�user_name@'144.155.166.%'适用äº�144.155.166 C级子网中的任何主机的user_nameã€�
简单形å¼�user_nameæ˜�user_name@'%'的同义词ã€�
MySQL不支æŒ�usernames中的通配符。通过把带æœ�User=''的登录项插入åˆ�mysql.user表中,或通过使用GRANT语句创建一个带有空名称的用户,可以定义匿名用户ï¼�
mysql> GRANT ALL ON test.* TO ''@'localhost' ...
当把带引号的值是,需使用反勾å��(â€�`â€�)为数据库、表、列和子程序名称加引号。使用单引号(â€�'â€�)ä¸�hostnamesã€�usernameså’� 密码加引号ã€�
警告:如果您允许匿名用户连接åˆ�MySQL服务器,则您应该同时向所有本地用户授äº�user_name@localhost权限。否则,当有名称的用户试图从本地机器登录MySQL服务器时ï¼�mysql.user表中的用äº�localhost的匿名用户帐户会被使用ã€�
您可以通过执行以下查询来确定是否这适合于您。以下查询列举了所有匿名用户:
mysql> SELECT Host, User FROM mysql.user WHERE User='';
如果您想要删除本地匿名用户账户,以避免出现刚才谈到的问题,则需使用以下语句ï¼�
mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
mysql> FLUSH PRIVILEGES;
GRANT支持最长为60个字符的hostnames。数据库、表、列和子程序名称最长可ä¸�64个字符ã€�Usernames最长可ä¸�16个字符ã€� 注释:不能通过更改mysql.user表来改变usernames的允许长度。如果试图这么做,会导致出现不可预见的问题,可能会造成用户无法登录MySQL服务器。除了采用由MySQL公司提供的用于升çº�MySQL服务器的mysql_fix_privilege_tables原稿之外ï¼�请您不要以任何方式变更授权表ã€�
对于表或列的权限是作为各个权限层级的逻辑OR权限被附加形成的。例如,如果mysql.user表指定一个用户拥有全局SELECT权限,则该权限不能被数据库、表或列层级的登录项定义ã€�
可以按下列方法计算列权限ï¼�
global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
在多数情况下,您只在一个权限层级下向用户授予权利,所以寿命通常不是那么复杂。有关权限检查规程的细节,请参见5.7节,“MySQL访问权限系统â€�ã€�
如果您对一个在mysql.user表中不存在的username/hostname组合授予权限,则增加一个登录项并保持在此处,直到使ç”�DELETE语句删除为止。换句话说,GRANT可以创建用户表登录项,但æ˜�REVOKE不会取消它们;您必须使用DROP USERæˆ�DELETE明确地操作ã€�
如果创建了一个新的用户,或者如果您拥有全局授权权限,则用户密码被设置为ç”�IDENTIFIED BY子句指定的密码(如果给定了一个)。如果用户已拥有了一个密码,则此密码被新密码替代ã€�
警告:如果您创建了一个新用户,但是不指定IDENTIFIED BY子句,则用户没有 密码。这是很不安全的。不过,您可以启ç”�NO_AUTO_CREATE_USER SQL模式,来防止GRANT创建一个新用户(否åˆ�GRANT会这么做),除非给定äº�IDENTIFIED BY来为新用户提供一个密码ã€�
使用SET PASSWORD语句也可以设置密码。请参见13.5.1.5节,“SET PASSWORD语法â€�ã€�
åœ�IDENTIFIED BY子句中,密码应被作为文字密码只被给定。没有必要使ç”�PASSWORD()函数,因为该函数用于SET PASSWORD语句。例如:
GRANT ... IDENTIFIED BY 'mypass';
如果您不想以明白的文字发送密码,并且您知é��PASSWORD()返回给密码的混编值,则您可以指定混编值,前面加入关键è¯�PASSWORDï¼�
GRANT ...
IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
在一ä¸�C程序中,您可以通过使用make_scrambled_password() C API函数得到混编值ã€�
如果您为一个数据库授予权限,则åœ�mysql.db表中,会根据需要创建登录项。如果使ç”�REVOKE删除了所有的数据库权限,则本登录项被删除ã€�
如果一个用户不拥有表权限,则当用户申请表清单时(例如,使用SHOW TABLES语句),表名称不显示ã€�
SHOW DATABASES权限允许账户通过发布SHOW DATABASE语句来观看数据名称。不拥有此权限的账户只能看到他们拥有部分权限的数据库,并且如果使ç”�--skip-show-database选项启动服务器,则根本不能使用本语句ã€�
WITH GRANT OPTION子句给予用户能力,可以在指定的权限层级,向其它用户给定其拥有的任何权限。您应该留心您给予了è°�GRANT OPTION权限,因为拥有不同权限的两个用户可以联合使用权限ï¼�
您不能向其它用户授予您自己没有的权限ï¼�GRANT OPTION权限只允许您赋予您自己拥有的权限ã€�
要注意,当您在某个特定权限层级向一个用户授äº�GRANT OPTION权限时,用户拥有的该层级的任何权限(或未来将被给定的权限)也可以由该用户授予。假设您向一个用户赋予了数据åº�INSERT权限。如果您然后赋予数据åº�SELECT权限,并指定äº�WITH GRANT OPTION,则该用户不仅可以向其它用户给予SELECT权限,还可以给予INSERT。如果您然后向用户授予数据库UPDATE权限,则用户可以授予INSERT, SELECTå’�UPDATEã€�
您不应该向一个常规用户授äº�ALTER权限。如果您这么做,则该用户可以尝试通过对表重新命名来破坏授权系统!
The MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR count, and MAX_CONNECTIONS_PER_HOUR count options limit the number of queries, updates, and logins a user can perform during any given one-hour period. If count is 0 (the default), this means that there is no limitation for that user. MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR countå’�MAX_CONNECTIONS_PER_HOUR count选项限制了在任何给定的一小时期间,用户可以执行的查询、更新和登录的数目。如æž�countæ˜�0(默认值),这意味着,对该用户没有限制ã€�
MAX_USER_CONNECTIONS count选项限制了账户可以同时进行的连接的最大数目。如æž�countæ˜�0(默认值),则max_user_connections系统可以决定è¯� 账户同时连接的数目ã€�
注释:要对一个原有的用户指定任何这类资源限制型选项,同时又不影响原有的权限,需使用GRANT USAGE ON *.* ... WITH MAX_...ã€�
è§�5.8.4节,“限制账户资源â€�ã€�
除了根据username和密码进行常规鉴定外ï¼�MySQL还可以检æŸ�X509证明属性。要ä¸�MySQL账户指定ä¸�SSL有关的选项,需使用GRANT语句çš�REQUIRE子句。(要了解有关在MySQL中使ç”�SSL的背景信息,请参è§�5.8.7节,“使用安全连接â€�。)
对于一个给定的账户,有多种可能性可以限制连接类型:
· 如果账户没有SSLæˆ�X509要求,并且如æž�usernameå’� 密码是有效的,则允许不加密连接。但是,如果客户端有正确的证明和关键文件,则根据客户端的选择,也可以使用加密连接ã€�
· REQUIRE SSL选项用于告知服务器,对于该账户只允许SSL加密连接。注意,如果有允许任何非SSL连接的访问控制记录,则本选项可以被忽略ã€�
· mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
· -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;
· REQUIRE X509意味着客户端必须拥有一个有效证明,除非不需要确切的证明、发布者和主题。唯一的要求是,应可以使用CA证明其中之一来验证签名ã€�
· mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
· -> IDENTIFIED BY 'goodsecret' REQUIRE X509;
· REQUIRE ISSUER 'issuer'用于对连接尝试进行限定,客户端必须出示一个由CAâ€�issuer’发布的有效çš�X509证明。如果客户端出示的证明是有效的,但是有一个不同的发布者,则服务器会拒绝连接。使ç”�X509证明就意味着要加密,所以在这种情况下,SSL选项是不必要的ã€�
· mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
· -> IDENTIFIED BY 'goodsecret'
· -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
· O=MySQL Finland AB/CN=Tonu Samuel/[email protected]';
注意ï¼�ISSUER值应被作为一个单一字符串输入ã€�
· REQUIRE SUBJECT 'subject'用于对连接尝试进行限定,客户端必须出示一个包含主é¢�subject的有效的X509证明。如果客户端出示的证明是有效的,但是有一个不同的主题,则服务器会拒绝连接ã€�
· mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
· -> IDENTIFIED BY 'goodsecret'
· -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
· O=MySQL demo client certificate/
· CN=Tonu Samuel/[email protected]';
注意ï¼�SUBJECT值应被作为一个单一字符串输入ã€�
· 需è¦�REQUIRE CIPHER 'cipher'来确认使用了密码和足够长度的关键字。如果使用了采用短型加密关键字的旧算法,SSL本身会比较脆弱。使用本选项,您可以要求使用特定的密码方法来许可一个连接ã€�
· mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
· -> IDENTIFIED BY 'goodsecret'
· -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';
SUBJECT, ISSUERå’�CIPHER选项可以åœ�REQUIRE子句中结合,如下ï¼�
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
-> IDENTIFIED BY 'goodsecret'
-> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
O=MySQL demo client certificate/
CN=Tonu Samuel/[email protected]'
-> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/[email protected]'
-> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
注意ï¼�SUBJECTå’�ISSUER值各自应被作为一个单一字符串输入ã€�
åœ�REQUIRE各选项之间ï¼�AND关键词是自选的ã€�
选项的顺序无所谓,但是选项不能被指定两次ã€�
å½�mysqld启动后,所有的权限被读入存储器中。要了解详细说明,请参见5.7.7节,“权限更改何时生效â€�ã€�
注意,如果您正在使用表权限或列权限,即使只对一个用户使用,服务器也会对所有用户检查表权限和列权限,这会略微降ä½�MySQL的速度。与此类似,如果您对某些用户限制查询、更新或连接的数目,则服务器必须监测这些值ã€�
标准SQL版本å’�MySQL版本çš�GRANT之间的最大区别是ï¼�
· åœ�MySQL中,权限ä¸�hostnameå’�username的组合有关,ä¸� 单一çš�username无关ã€�
· 标准SQL不拥有全局层级或数据库层级权限,也不支æŒ�MySQL支持的所有权限类型ã€�
· MySQL不支持标å‡�SQL TRIGGERæˆ�UNDER权限ã€�
· 标准SQL权限以一种分等级的方式进行组织。如果您取消一个用户,则用户被授予的所有权限都被撤销。在MySQL中,如果您使ç”�DROP USER,也会如此。请参见13.5.1.2节,“DROP USER语法â€�ã€�
· 在标å‡�SQL中,当您取消一个表时,对一个表的所有权限会被撤销。在标准SQL中,当您撤销一个权限时,根据该权限被授予的所有权限也会被撤销。在MySQL中,只有使用明确çš�REVOKE语句,或通过操作存储åœ�MySQL授权表中的值,才能取消权限ã€�
· åœ�MySQL中,可以只对一个表中的部分列拥æœ�INSERT权限。在此情况下,如果您忽略您不拥有INSERT权限的那些列,,您仍然可以对表执è¡�INSERT语句。如果没有启用严格的SQL模式,则被忽略的列被设置为各自隐含的默认值。在严格模式下,如果某个被忽略的列没有默认值,则该语句被拒绝ã€�5.3.2节,“SQL服务器模式â€�对严格模式进行了讨论ã€�13.1.5节,“CREATE TABLE语法â€�对隐含默认值进行了讨论ã€�
您不拥有INSERT权限的列被设置为各自的默认值。标å‡�SQL要求您拥有所有列çš�INSERT权限ã€�
åœ�MySQL中,如果您只拥有一个表中的部分列的INSERT权限,同时,如果您从INSERT语句中忽略您不拥有权限的列,则您仍然可以对表执行INSERT语句;那些列将被设置为各自的默认值。在严格模式下(即当sql_mode='traditional'时,如果某些被忽略的列没有默认值,åˆ�INSERT语句将被拒绝ã€�
SET PASSWORD = PASSWORD('some password')
SET PASSWORD FOR user = PASSWORD('some password')
SET PASSWORD语句用于向一个原æœ�MySQL用户 账户赋予一个密码ã€�
第一个语法为当前用户设置密码。已使用一个非匿名账户连接到服务器上的任何客户即都可以更改该账户的密码ã€�
第二个语法为当前服务器主机上的一个特定账户设置密码。只有拥æœ�mysql数据åº�UPDATE权限的客户端可以这么做ã€�user值应ä»�user_name@host_name的格式被给定,此å¤�user_nameå’�host_nameä¸�mysql.user表登录项çš�Userå’�Host列中列出的完全一样。举例说明,如果您有一个登录项ï¼�Userå’�Host列值为'bob'å’�'%.loc.gov',您应该按如下方法写语句ï¼�
mysql> SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
这相当于以下语句ï¼�
mysql> UPDATE mysql.user SET Password=PASSWORD('newpass')
-> WHERE User='bob' AND Host='%.loc.gov';
mysql> FLUSH PRIVILEGES;
注释:如果您正在使用一ä¸�4.1以前的客户端连接到一ä¸�MySQL 4.1æˆ�MySQL 4.1以后的服务器,则在阅è¯�5.7.9节,“MySQL 4.1中的密码哈希处理â€�之前,不能使用前面的SET PASSWORDæˆ�UPDATE语句ã€� 密码格式åœ�MySQL 4.1中变更了,并且在特定情况下,如果您更改密码,您可能无法在连接到服务器上ã€�
您可以通过执行SELECT CURRENT_USER()观看您当前的鉴定user@host登录项ã€�
ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
本语句用于分析和存储表的关键字分布。在分析期间,使用一个读取锁定对表进行锁定。这对于MyISAM, BDBå’�InnoDB表有作用。对äº�MyISAM表,本语句与使用myisamchk -a相当ã€�
MySQL使用已存储的关键字分布来决定,当您对除常数以外的对象执行联合时,表按什么顺序进行联合ã€�
本语句会返回一个含有以下列的表ï¼�
|
� |
� |
|
Table |
表名ç§� |
|
Op |
进行分析 |
|
Msg_type |
状态、错误、信息或警告之一 |
|
Msg_text |
消息 |
您可以使ç”�SHOW INDEX语句检查已存储的关键字分布。请参见13.5.4.11节,“SHOW INDEX语法â€�ã€�
如果从上一ä¸�ANALYZE TABLE语句开始,表没有变化,则不再分析该表ã€�
ANALYZE TABLE语句被写入二进制日志中,除非使用了自选的NO_WRITE_TO_BINLOG关键词(或其别名LOCAL)ã€�
BACKUP TABLE tbl_name [, tbl_name] ... TO '/path/to/backup/directory'
注释:本语句不理想。我们正在努力寻找一种更好的替代方式,该方式将提供在线备份能力。同时,也可以使ç”�mysqlhotcopy原本替代ã€�
BACKUP TABLE用于在刷新了所有对磁盘的缓冲变更后,把恢复表所需的最少数目的表文件拷贝到备份目录中。本语句只对MyISAM表起作用。它可以拷贝.frm定义文件å’�.MYD数据文件ã€�.MYI索引文件可以从这两个文件中重建。本目录应被指定为一个完整的路径名ã€�
在使用本语句前,请参è§�5.9.1节,“数据库备份â€�ã€�
在备份期间,为每个表保持一个读取锁定,每次一个,在正在备份时锁定。如果您想要把多个表作为一个快照来备份(防止它们在备份操作过程中被更改),您必须实现发布一ä¸�LOCK TABLES语句,以获得对一个组群中的每个表的读取锁定ã€�
该语句会返回一个含有以下列的表ï¼�
|
� |
� |
|
Table |
表名ç§� |
|
Op |
进行备份 |
|
Msg_type |
状态、错误、信息或警告之一 |
|
Msg_text |
消息 |
CHECK TABLE tbl_name [, tbl_name] ... [option] ...
option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
检查一个或多个表是否有错误ã€�CHECK TABLEå¯�MyISAMå’�InnoDB表有作用。对äº�MyISAM表,关键字统计数据被更新ã€�
CHECK TABLE也可以检查视图是否有错误,比如在视图定义中被引用的表已不存在ã€�
CHECK TABLE语句会返回一个含有以下列的表ï¼�
|
� |
� |
|
Table |
表名ç§� |
|
Op |
进行检æŸ� |
|
Msg_type |
状态、错误、信息或错误之一 |
|
Msg_text |
消息 |
注意,该语句可能会为每个被检查的表产生多行信息。最后一行有一ä¸�Msg_type状态值ã€�Msg_text通常应为OK。如果您没有得到OK,或表已经更新了,则您通常应该运行修复后的表。请参见5.9.4节,“表维护和崩溃恢复â€�。表已经更新了,这意味着表的存储引擎指示没有必要检查表ã€�
可以给予的不同的检查选项列于下表中。这些选项只适用于检æŸ�MyISAM表。对äº�InnoDB表和视图,这些选项被忽略ã€�
|
类型 |
意义 |
|
QUICK |
不扫描行,不检查错误的链接ã€� |
|
FAST |
只检查没有被正确关闭的表ã€� |
|
CHANGED |
只检查上次检查后被更改的表,和没有被正确关闭的表ã€� |
|
MEDIUM |
扫描行,以验证被删除的链接是有效的。也可以计算各行的关键字校验和,并使用计算出的校验和验证这一点ã€� |
|
EXTENDED |
对每行的所有关键字进行一个全面的关键字查找。这可以确保表是100%一致的,但是花的时间较长ã€� |
如果没有指定QUICK, MEDIUMæˆ�EXTENDED选项,则对于动态格å¼�MyISAM表,默认检查类型是MEDIUM。这与对表运è¡�myisamchk --medium-check tbl_name的结果相同。对于静态格å¼�MyISAM表,默认检查类型也æ˜�MEDIUM,除é��CHANGEDæˆ�FAST已被指定。在此情况下,默认值为QUICK。对äº�CHANGEDå’�FAST,行扫描被跳过,因为行极少被破坏ã€�
您可以组合检查选项,如下面的例子所示。该例子对表进行了一个快速检查,来查看该表是否被正确关闭ï¼�
CHECK TABLE test_table FAST QUICK;
注释:在有些情况下,CHECK TABLE会更改表。如果表被标记为â€�corrupted”或â€�not closed properly”,则出现这种情况。但æ˜�CHECK TABLE不会找出表中的问题。在这种情况下,CHECK TABLE会把表标记为良好ã€�
如果一个表被破坏,很有可能问题在索引中,而不在数据部分中。所有前述的检查类型都可以彻底地检查索引,因此,可以找出多数的错误ã€�
如果您只想要检查您假定的表是良好的,您应该不使用检查选项æˆ�QUICK选项。当您时间匆忙时,应使用QUICKã€�QUICK无法找出数据文件中的错误的风险非常小。(在多数情况下,在正常使用中,MySQL应能在数据文件中找出错误。如果找出了错误,表被标记为â€�corrupted”,并不能被使用,直到修复为歀€‚)
如果您想要时常检查表ï¼�FASTå’�CHANGED多数情况下从原本中被使用(例如,ä»�cron中被执行)。在多数情况下,FAST优先äº�CHANGED。(只有一种情å†�FAST不优先于CHANGED,那就是当您怀疑您åœ�MyISAM代码中发现了错误。)
å½�MySQL试图通过关键字更新一行或查找一行时,如果您已经运行了一个常规检查后但仍得到来自表的奇怪的错误,此时使ç”�EXTENDED。(如果常规的检查运行成功,则基本用不着EXTENDED。)
è¢�CHECK TABLE报告的部分问题不会被自动修正ï¼�
· 发现行。此行中ï¼�auto_increment列有0值ã€�
这意味着,您在表中有一行,该行çš�AUTO_INCREMENT索引列包å��0值。(可以通过使用UPDATE语句,明确地把列设置ä¸�0,以创建一ä¸�AUTO_INCREMENT列为0的行。)
这本身不是一个错误,但是如果您决定转储表并恢复表,或对表进行ALTER TABLE,那么会导致出现麻烦。在此情况下ï¼�AUTO_INCREMENT列会根据AUTO_INCREMENT列的结果更改值,这会导致出现问题,如重复关键字错误等ã€�
要消除警告,只需执行一ä¸�UPDATE语句,把列设置为é™�0以外的值ã€�
CHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]
报告一个表校验和ã€�
如果指定äº�QUICK,则报告活性表校验和,否则报告NULL。这是非常快的。活性表通过指定CHECKSUMï¼�1表选项启用,目前只支持用于MyISAM表。请参见13.1.5节,“CREATE TABLE语法â€�ã€�
åœ�EXTENDED模式下,整个表被一行一行地读取,并计算校验和。对于大型表,这是非常慢的ã€�
默认情况下,如果既没有指å®�QUICK,也没有指定EXTENDED,并且如果表存储引擎支持,则MySQL返回一个活性校验和,否则会对表进行扫描ã€�
CHECKSUM TABLE对于不存在的表会返回NULL。对于这种情况,会生成一个警告ã€�
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
如果您已经删除了表的一大部分,或者如果您已经对含有可变长度行的表(含æœ�VARCHAR, BLOBæˆ�TEXT列的表)进行了很多更改,则应使用OPTIMIZE TABLE。被删除的记录被保持在链接清单中,后续的INSERT操作会重新使用旧的记录位置。您可以使用OPTIMIZE TABLE来重新利用未使用的空间,并整理数据文件的碎片ã€�
在多数的设置中,您根本不需要运è¡�OPTIMIZE TABLE。即使您对可变长度的行进行了大量的更新,您也不需要经常运行,每周一次或每月一次即可,只对特定的表运行ã€�
OPTIMIZE TABLE只对MyISAM, BDBå’�InnoDB表起作用ã€�
对于MyISAM表,OPTIMIZE TABLE按如下方式操作:
1. 如果表已经删除或分解了行,则修复表ã€�
2. 如果未对索引页进行分类,则进行分类ã€�
3. 如果表的统计数据没有更新(并且通过对索引进行分类不能实现修复),则进行更新ã€�
对于BDB表,OPTIMIZE TABLE目前被映射到ANALYZE TABLE上。对äº�InnoDB表,OPTIMIZE TABLE被映射到ALTER TABLE上,这会重建表。重建操作能更新索引统计数据并释放成簇索引中的未使用的空间。请参见13.5.2.1节,“ANALYZE TABLE语法â€�ã€�
使用â€�skip-new或â€�safe-mode选项可以启动mysqld。通过启动mysqld,您可以ä½�OPTIMIZE TABLE对其它表类型起作用ã€�
注意,在OPTIMIZE TABLE运行过程中,MySQL会锁定表ã€�
OPTIMIZE TABLE语句被写入到二进制日志中,除非使用了自选的NO_WRITE_TO_BINLOG关键词(或其别名LOCAL)。已经这么做了,因此,用äº�MySQL服务器的OPTIMIZE TABLE命令的作用相当于一个复制主服务器,在默认情况下,这些命令将被复制到复制从属服务器中ã€�
REPAIR [LOCAL | NO_WRITE_TO_BINLOG] TABLE
tbl_name [, tbl_name] ... [QUICK] [EXTENDED] [USE_FRM]
REPAIR TABLE用于修复被破坏的表。默认情况下ï¼�REPAIR TABLEä¸�myisamchk --recover tbl_name具有相同的效果ã€�REPAIR TABLEå¯�MyISAMå’�ARCHIVE表起作用。请参见15.1节,“MyISAM存储引擎â€�, 15.8节,“ARCHIVE存储引擎â€�ã€�
通常,您基本上不必运行此语句。但是,如果灾难发生ï¼�REPAIR TABLE很有可能ä»�MyISAM表中找回所有数据。如果您的表经常被破坏,您应该尽力找到原因,以避免使ç”�REPAIR TALBE。请参见A.4.2节,“如果MySQL依然崩溃,应作些什么â€�。同时也è§�15.1.4节,“MyISAM表方面的问题â€�ã€�
本语句会返回一个含有以下列的表ï¼�
|
� |
� |
|
Table |
表名ç§� |
|
Op |
进行修复 |
|
Msg_type |
状态、错误、信息或警告之一 |
|
Msg_text |
消息 |
对于每个被修复的表,REPAIR TABLE语句会产生多行的信息。上一行含有一ä¸�Msg_type状态值ã€�Msg_test通常应为OK。如果您没有得到OK,您应该尝试使用myisamchk --safe-recover修复表,因为REPAIR TABLE尚不会执行所有的myisamchk选项。我们计划在将来使它的灵活性更强ã€�
如果给定äº�QUICK,则REPAIR TABLE会尝试只修复索引树。这种类型的修复与使ç”�myisamchk --recover --quick相似ã€�
如果您使ç”�EXTENDED,则MySQL会一行一行地创建索引行,代替使用分类一次创建一个索引。这种类型的修复与使ç”�myisamchk --safe-recover相似ã€�
对于REPAIR TABLE,还有一ç§�USE_FRM模式可以利用。如æž�.MYI索引文件缺失或标题被破坏,则使用此模式。在这种模式下,MySQL可以使用来自.frm文件重新创建.MYI文件。这种修复不能使ç”�myisamchk来完成ã€� 注释:只能在您不能使用常è§�REPAIR模式是,才能使用此模式ã€�.MYI标题包含重要的表元数据(特别是,当前çš�AUTO_INCREMENT值和Delete链接)。这些元数据åœ�REPAIR...USE_FRM中丢失。如果表被压缩,则不能使ç”�USE_FRM。因为本信息也存储在.MYI文件中ã€�
REPAIR TABLE语句被写入二进制日志中,除非使用了自选的NO_WRITE_TO_BINLOG关键词(或其别名LOCAL)ã€�
警告:如果在REPAIR TABLE运行过程中,服务器停机,则在重新启动之后,在执行其它操作之前,您必须立刻对表再执行一ä¸�REPAIR TABLE语句。(通过制作一个备份来启动是一个好办法。)再最不利情况下,您可以有一个新的干净的索引文件,不含有关数据文件的信息。然后,您执行的下一个操作会覆盖数据文件。这很少发生,但是是有可能的ã€�
RESTORE TABLE tbl_name [, tbl_name] ... FROM '/path/to/backup/directory'
用于恢复来自ç”�BACKUP TABLE制作的备份的表。原有的表不会被覆盖;如果您试图覆盖一个原有的表,会发生错误。和BACKUP TABLE一样,RESTORE TABLE目前只对MyISAM表起作用。目录应被指定为一个完整路径名ã€�
每个表的备份包括å…�.frm格式文件å’�.MYD数据文件。恢复操作会恢复这些文件,然后使用这些文件来重建.MYI索引文件。恢复操作比备份操作花的时间更长,这是因为需要重建索引。表含有的索引越多,花的时间就越长ã€�
该语句会返回一个含有以下列的表ï¼�
|
� |
� |
|
Table |
表名ç§� |
|
Op |
进行恢复 |
|
Msg_type |
状态、错误、信息或警告之一 |
|
Msg_text |
消息 |
SET variable_assignment [, variable_assignment] ...
variable_assignment:
user_var_name = expr
| [GLOBAL | SESSION] system_var_name = expr
| @@[global. | session.]system_var_name = expr
SET用于设置不同类型的变量。这些变量会影响服务器或客户端的操作ã€�SET可以用于向用户变量或系统变量赋值ã€�
用于分配账户密码çš�SET PASSWORD语句åœ�13.5.1.5节,“SET PASSWORD语法â€�中进行了讨论ã€�
多数系统变量可以在运行时间被更改。可以被动态设置的系统变量åœ�5.3.3.1节,“动态系统变量â€�中进行了讨论ã€�
注释:旧版本çš�MySQL采用SET OPTION作为这个命令,但是由于有äº�SET,现在不赞成使用SET OPTIONã€�
以下例子显示了您可以用于设置变量的不同语法ã€�
用户变量可以被写ä½�@var_name,并可以进行如下设置ï¼�
SET @var_name = expr;
åœ�9.3节,“用户变量â€�中给出了有关用户变量的更多信息ã€�
系统变量可以被作ä¸�var_name引用åˆ�SET语句中。在名称的前面可以自选地添加GLOBALæˆ�@@global,以明确地指示该变量是全局变量。或者在名称前面添加SESSION, @@session,或@@,以指示它是一个会话变量ã€�LOCALå’�@@localæ˜�SESSIONå’�@@session地同义词。如果没有修改符,则SET设置会话变量ã€�
支持系统变量çš�@@var_name语法,以便使MySQL语法与其它数据库系统相兼容ã€�
如果您在同一个语句中设置多个系统变量,则最后一ä¸�GLOBALæˆ�SESSION选项被用于没有指定模式的变量ã€�
SET sort_buffer_size=10000;
SET @@local.sort_buffer_size=10000;
SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;
SET @@sort_buffer_size=1000000;
SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;
如果您使ç”�SESSION(默认情况)设置一个系统变量,则该值仍然有效,直到当前会话结束为止,或者直到您吧变量设置为一个不同的值为歀€‚如果您使用GLOBAL(要æ±�SUPER权限)来设置一个系统变量,则该值被记住,并被用于新的连接,直到服务器重新启动为歀€‚如果您想要进行永久式变量设置,您应该把它放入一个选项文件。请参见4.3.2节,“使用选项文件â€�ã€�
为了防止不正确的使用,如果您使用SET GLOBAL时同时使用了一个只能与SET SESSION同时使用的变量,或者如果您在设置一个全局变量时未指定GLOBAL(或@@),åˆ�MySQL会产生一个错误ã€�
如果您想要把一ä¸�SESSION变量设置ä¸�GLOBAL值或把一ä¸�GLOBAL值设置为内部MySQL默认值,需使用DEFAULT关键词。例如,在把max_join_size会话值设置为全局值时,以下两个语句是一样的ï¼�
SET max_join_size=DEFAULT;
SET @@session.max_join_size=@@global.max_join_size;
您可以使ç”�SHOW VARIABLES来得到系统变量清单。(è§�13.5.4.21节,“SHOW VARIABLES语法â€�。)要获得与样式匹配的一个具体的变量名称或者名称清单,需使用LIKE子句,使用方法如下:
SHOW VARIABLES LIKE 'max_join_size';
SHOW GLOBAL VARIABLES LIKE 'max_join_size';
要得到名称与样式匹配的变量的清单,需使用通配符â€�%’:
SHOW VARIABLES LIKE 'have%';
SHOW GLOBAL VARIABLES LIKE 'have%';
通配符可以被用于相匹配的样式中的任何位置ã€�
您也可以通过使用@@[global.|local.]var_name语法å’�SELECT来得到值:
SELECT @@max_join_size, @@global.max_join_size;
当您使用SELECT @@var_name(即您不指定全局、会话或本地)来恢复一个变量时,则MySQL会返å›�SESSION值(如果存在)或è€�GLOBAL值ã€�
以下清单用于描述带有非标准语法的变量,或描述在系统变量清单中(见5.3.3节,“服务器系统变量â€�。)中没有描述的变量。尽管这些变量没有被SHOW VARIABLES显示,但是您可以使用SELECT来获得它们的值(例外情况是,使用CHARACTER SETå’�SET NAMES)。例如:
mysql> SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
| 1 |
+--------------+
· AUTOCOMMIT = {0 | 1}
设置autocommit模式。如果设置为1,则所有对表的更改会立刻生效。如果设置为0,则您必须使ç”�COMMIT来接受一个事务,或使ç”�ROLLBACK来取消它。如果您æŠ�AUTOCOMMIT模式ä»�0改为1,则MySQL会对开放事务执行一个自åŠ�COMMIT。开始一个事务的另一种方法是使用一ä¸�START TRANSACTIONæˆ�BEGIN语句。请参见13.4.1节,“START TRANSACTION, COMMIT和ROLLBACK语法â€�ã€�
· BIG_TABLES = {0 | 1}
如果设置ä¸�1,所有的临时表被存储在磁盘中,而不是存储在储存期中。这样会稍微慢些,但是对于需要一个大型临时表çš�SELECT操作,不会发ç”�The table tbl_name is full错误。对于一个新连接,默认值为0(使用存储器内部临时表)。通常,您不必设置此变量,因为根据需要,存储器内部表会被自动转换为以磁盘为基础的表。( 注释:本变量以前被命名为SQL_BIG_TABLES。)
· CHARACTER SET {charset_name | DEFAULT}
本语句使用给定的映射为所有来自客户端和指向客户端的字符串建立映射。您可以通过åœ�MySQL源分布中编辑sql/convert.cc来添加新的映射ã€�SET CHARACTER SET用于设定三个会话系统变量ï¼�character_set_clientå’�character_set_results被设置为给定的字符集ï¼�character_set_connection被设置为character_set_database值ã€�
可以通过使用DEFAULT值恢复默认的映射ã€�
注意ï¼�SET CHARACTER SET的语法与设置其它选项的语法不同ã€�
· FOREIGN_KEY_CHECKS = {0 | 1}
如果设置ä¸�1(默认情况),则检æŸ�InnoDB表的外键限制条件。如果设置为0,则限制条件被忽略。如果重新载å…�InnoDB表时按照的顺序与上级/下级目录所要求的顺序不同,此时禁用外键检查是有用的。请参见15.2.6.4节,“FOREIGN KEY约束â€�ã€�
· IDENTITY = value
该变量是LAST_INSERT_ID变量的同义词。该变量的作用是保持与其它数据库兼容。您可以使用SELECT @@IDENTITY读取其值,并可以使ç”�SET IDENTITY设置它ã€�
· INSERT_ID = value
用于设置将被以下INSERTæˆ�ALTER TABLE语句使用的值。此值在插入一ä¸�AUTO_INCREMENT值时使用。本语句主要和二进制日志同时使用ã€�
· LAST_INSERT_ID = value
用于设定将从LAST_INSERT_ID()被返回的值。当您在用于更新表的语句中使ç”�LAST_INSERT_ID()时,它被存储在二进制日志中。设置此变量不会更新ç”�mysql_insert_id() C API函数返回的值ã€�
· NAMES {'charset_name' | DEFAULT}
SET NAMES用于把三个会话系统变é‡�character_set_client, character_set_connectionå’�character_set_results设置为给定的字符集。把character_set_connection设置ä¸�charset_name时,同时æŠ�collation_connection设置ä¸�charset_name的默认整序ã€�
使用一ä¸�DEFAULT值可以恢复默认的映射ã€�
注意ï¼�SET NAMES的语法与用于设置其它选项的语法不同ã€�
· ONE_SHOT
这不是一个服务器系统变量,但是它可以被用来影响用于设置字符集、整序和时区的变量的效果ã€�ONE_SHOT主要被用于复制:mysqlbinlog使用SET ONE_SHOT来暂时地修改字符集、整序和时区变量的值,以反映出它们原先的值ã€�
您不能在使用ONE_SHOT时使用除允许的变量以外的变量;如果您这么做,您会得到如下错误ï¼�
mysql> SET ONE_SHOT max_allowed_packet = 1;
ERROR 1382 (HY000): The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server
如果同时使用ONE_SHOT和被允许的变量,则会根据要求更改变量,但是会在下一个语句后,重新设置所有的字符集、整序和与时区有关的服务器系统变量。唯一的例外是,当下一个语句是SET语句时,不会进行重新设置。换句话说,在下一个非SET语句之后,才会进行重新设置。例如:
mysql> SET ONE_SHOT character_set_connection = latin5;
mysql> SET ONE_SHOT collation_connection = latin5_turkish_ci;
mysql> SHOW VARIABLES LIKE '%_connection';
+--------------------------+-------------------+
| Variable_name | Value |
+--------------------------+-------------------+
| character_set_connection | latin5 |
| collation_connection | latin5_turkish_ci |
+--------------------------+-------------------+
mysql> SHOW VARIABLES LIKE '%_connection';
+--------------------------+-------------------+
| Variable_name | Value |
+--------------------------+-------------------+
| character_set_connection | latin1 |
| collation_connection | latin1_swedish_ci |
+--------------------------+-------------------+
· SQL_NOTES = {0 | 1}
当设置为1时(默认情况),“注意”一级的警报被记录下来。当设置ä¸�0时,“注意”警告被压制ã€�Mysqldump包含输出,用于把此变量设置为0,这样,对于不会影响重新载入操作整体性的事件,重新载入转储文件时不会产生警告ã€�
· SQL_AUTO_IS_NULL = {0 | 1}
如果设置ä¸�1(默认情况),您可以通过使用以下结构查找包含一ä¸�AUTO_INCREMENT列的表的最后插入的行:
WHERE auto_increment_column IS NULL
此性质被有äº�ODBC程序,比å¦�Access使用ã€�
· SQL_BIG_SELECTS = {0 | 1}
如果设定ä¸�0,则MySQL会放弃有可能会花很长时间来执行的SELECT语句(也就是,对于这些语句,优化程序估算被检查的行的数目超过äº�max_join_size的值)。当一个不妥当çš�WHERE语句被发布后,本语句有用。一个新连接的默认值为1,这可以允许所有的SELECT语句ã€�
如果您把max_join_size系统变量设置为除DEFAULT以外的值,åˆ�SQL_BIG_SELECTS被设置为0ã€�
· SQL_BUFFER_RESULT = {0 | 1}
SQL_BUFFER_RESULT会迫使来è‡�SELECT语句的结果被放入临时表中。这可以帮助MySQL早点解除表锁定。当需要花较长时间把结果发送给客户端时,这是有好处的ã€�
· SQL_LOG_BIN = {0 | 1}
如果设置ä¸�0,则客户端的二进制日志中不会记录日志。客户端必须拥有SUPER权限来设置此选项ã€�
· SQL_LOG_OFF = {0 | 1}
如果设置ä¸�1,则此客户端的总查询日志中不会记录日志。客户端必须拥有SUPER权限来设置此选项ã€�
· SQL_LOG_UPDATE = {0 | 1}
不赞成使用本变量。本变量被映射到SQL_LOG_BINã€�
· SQL_QUOTE_SHOW_CREATE = {0 | 1}
如果设置ä¸�1,则SHOW CREATE TABLE会对表和列的名称加引号。如果设置为0,则加引号操作被禁用。默认情况下,本选项被启用,因此对于含有需要加引号的名称的表,复制操作起作用。请参见13.5.4.5节,“SHOW CREATE TABLE语法â€�ã€�
· SQL_SAFE_UPDATES = {0 | 1}
如果设置ä¸�1,则MySQL会放弃在WHERE子句æˆ�LIMIT子句中不使用关键字的UPDATEæˆ�DELETE语句。这样,当关键字使用不正确时,也有可能理è§�UPDATEæˆ�DELETE语句。这样就可以更改或删除大量的行ã€�
· SQL_SELECT_LIMIT = {value | DEFAULT}
ä»�SELECT语句返回的记录的最大数目。对于一个新连接,默认值是â€�unlimited”。如果您更改了限值,可以使用SQL_SELECT_LIMIT DEFAULT值恢复默认值ã€�
如果SELECT有一ä¸�LIMIT子句,则LIMIT优先äº�SQL_SELECT_LIMIT值ã€�
SQL_SELECT_LIMT不适用于在被存储的子程序中执行çš�SELECT语句。它也不适用于不会产生将被返回到客户端的结果集合çš�SELECT语句。这些包括子查询中的SELECT语句ï¼�CREATE TABLE...SELECTå’�INSERT INTO...SELECTã€�
· SQL_WARNINGS = {0 | 1}
本变量用于控制当出现警告时,单行INSERT语句是否产生一个信息字符串。默认值为0。把值设置为1,来产生一个信息字符串ã€�
· TIMESTAMP = {timestamp_value | DEFAULT}
用于为此客户端设置时间。当您使用二进制日志来恢复行时,本语句用于得到原始的时间标记ã€�timestamp_value应为一ä¸�Unix时间标记,而不æ˜�MySQL时间标记ã€�
· UNIQUE_CHECKS = {0 | 1}
如果设置ä¸�1(默认情况),则会对InnoDB表中的二级索引执行唯一性检查。如果设置为0,则对于被插入到InnoDB的插入缓冲器中的索引登录项,不执行唯一性检查。如果您可以肯定您的数据不违反唯一性要求,则您可以把此值设定为0,以加快å��InnoDB导入大型表的速度ã€�
SHOW有多种形式,可以提供有关数据库、表、列或服务器状态的信息。本节叙述以下内容:
SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
SHOW CREATE DATABASE db_name
SHOW CREATE TABLE tbl_name
SHOW DATABASES [LIKE 'pattern']
SHOW ENGINE engine_name {LOGS | STATUS }
SHOW [STORAGE] ENGINES
SHOW ERRORS [LIMIT [offset,] row_count]
SHOW GRANTS FOR user
SHOW INDEX FROM tbl_name [FROM db_name]
SHOW INNODB STATUS
SHOW [BDB] LOGS
SHOW PRIVILEGES
SHOW [FULL] PROCESSLIST
SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']
SHOW TRIGGERS
SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
SHOW WARNINGS [LIMIT [offset,] row_count]
SHOW语句还有一些形式,可以提供有关复制型主服务器和从属服务器的信息。这些形式在13.6节,“复制语句â€�中进行了叙述ã€�
SHOW BINLOG EVENTS
SHOW MASTER LOGS
SHOW MASTER STATUS
SHOW SLAVE HOSTS
SHOW SLAVE STATUS
如果一个给定的SHOW语句的语法包括一ä¸�LIKE 'pattern'部分,则'pattern'是一个可以包å��SQL â€�%’和â€�_’通配符的字符串。对于把语句输出值限定为匹配值,本样式是有用的ã€�
SHOW CHARACTER SET [LIKE 'pattern']
SHOW CHARACTER SET语句用于显示所有可用的字符集。该语句取一个自选的LIKE子句。该子句指示哪些字符集名称可以匹配。举例说明:
mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
+---------+-----------------------------+-------------------+--------+
Maxlen列显示用于存储一个字符的最大的字节数目ã€�
SHOW COLLATION [LIKE 'pattern']
来自SHOW COLLATION的输出包括所有可用的字符集。该语句取一个自选的LIKE子句。该子句çš�pattern指示哪些整序名称可以匹配。举例说明:
mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 0 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+-------------------+---------+----+---------+----------+---------+
Default列指示对于其字符集,整序值是否是默认值ã€�Compiled指示字符集是否被编辑到服务器中ã€�Sortlen与对字符串(在字符集中表达)分类所需的存储器的数量有关ã€�
SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
SHOW COLUMNS显示在一个给定表中的各列的信息。对于试图,本语句也起作用ã€�
如果列类型与根据您的CREATE TABLE语句所预期的列类型不同,则需注意,当您创建或更改表时ï¼�MySQL有时会更改列类型。出现这种情况的条件åœ�13.1.5.1节,“沉寂的列规格变更â€�中进行了描述ã€�
FULL关键词会使得输出中包含您拥有的权限,并包含对每一列各自的评注ã€�
您可以使ç”�db_name.tbl_name作为tbl_name FROM db_name语法的另一种形式。换句话说,这两个语句是等价的:
mysql> SHOW COLUMNS FROM mytable FROM mydb;
mysql> SHOW COLUMNS FROM mydb.mytable;
SHOW FIELDSæ˜�SHOW COLUMNS的同义词。您也可以使ç”�mysqlshow db_name tbl_name命令列举表的各列ã€�
DESCRIBE语句提供ä¸�SHOW COLUMNS相近的信息。请参见13.3.1节,“DESCRIBE语法(获取关于列的信息)â€�ã€�
SHOW CREATE {DATABASE | SCHEMA} db_name
显示用于创建给定数据åº�CREATE DATABASE语句。也可以使用SHOW CREATE SCHEMAã€�
mysql> SHOW CREATE DATABASE test\G
*************************** 1. row ***************************
Database: test
Create Database: CREATE DATABASE `test`
/*!40100 DEFAULT CHARACTER SET latin1 */
mysql> SHOW CREATE SCHEMA test\G
*************************** 1. row ***************************
Database: test
Create Database: CREATE DATABASE `test`
/*!40100 DEFAULT CHARACTER SET latin1 */
SHOW CREATE TABLE tbl_name
显示用于创建给定表的CREATE TABLE语句。本语句对视图也起作用ã€�
mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE t (
id INT(11) default NULL auto_increment,
s char(60) default NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM
根据SQL_QUOTE_SHOW_CREATE选项ï¼�SHOW CREATE TABLE会对表名称和列名称加引号。请参见13.5.3节,“SET语法â€�ã€�
SHOW ENGINE engine_name {LOGS | STATUS }
SHOW ENGINE显示存储引擎的日志或状态信息。目前支持以下语句:
SHOW ENGINE BDB LOGS
SHOW ENGINE INNODB STATUS
SHOW ENGINE BDB LOGS显示原有BDB日志文件的状态信息。它会返回以下字段:
· File
通向日志文件的完整路径ã€�
· Type
日志文件类型(用äº�Berkeley DB日志文件çš�BDB)ã€�
· Status
日志文件的状态(如果文件可以被取消,则为FREE。如果文件被事务子系统需要,则为IN USEï¼�
SHOW ENGINE INNODB STATUS显示InnoDB存储引擎状态的全面信息ã€�
这些语句的旧的同义词(现在不赞成使用)是SHOW [BDB] LOGSå’�SHOW INNODB STATUSã€�
SHOW ENGINE可以ä»�MySQL 4.1.2起使用ã€�
SHOW [STORAGE] ENGINES
SHOW ENGINES显示存储引擎的状态信息。对于检查一个存储引擎是否被支持,或者对于查看默认引擎是什么,本语句十分有用ã€�SHOW TABLE TYPES是同义词,但不赞成使用ã€�
mysql> SHOW ENGINES\G *************************** 1. row *************************** Engine: MyISAM Support: DEFAULT Comment: Default engine as of MySQL 3.23 with great performance *************************** 2. row *************************** Engine: MEMORY Support: YES Comment: Hash based, stored in memory, useful for temporary tables *************************** 3. row *************************** Engine: HEAP Support: YES Comment: Alias for MEMORY *************************** 4. row *************************** Engine: MERGE Support: YES Comment: Collection of identical MyISAM tables *************************** 5. row *************************** Engine: MRG_MYISAM Support: YES Comment: Alias for MERGE *************************** 6. row *************************** Engine: ISAM Support: NO Comment: Obsolete storage engine, now replaced by MyISAM *************************** 7. row *************************** Engine: MRG_ISAM Support: NO Comment: Obsolete storage engine, now replaced by MERGE *************************** 8. row *************************** Engine: InnoDB Support: YES Comment: Supports transactions, row-level locking, and foreign keys *************************** 9. row *************************** Engine: INNOBASE Support: YES Comment: Alias for INNODB *************************** 10. row *************************** Engine: BDB Support: NO Comment: Supports transactions and page-level locking *************************** 11. row *************************** Engine: BERKELEYDB Support: NO Comment: Alias for BDB *************************** 12. row *************************** Engine: NDBCLUSTER Support: DISABLED Comment: Clustered, fault-tolerant, memory-based tables *************************** 13. row *************************** Engine: NDB Support: DISABLED Comment: Alias for NDBCLUSTER *************************** 14. row *************************** Engine: EXAMPLE Support: NO Comment: Example storage engine *************************** 15. row *************************** Engine: ARCHIVE Support: YES Comment: Archive storage engine *************************** 16. row *************************** Engine: CSV Support: YES Comment: CSV storage engine *************************** 17. row *************************** Engine: FEDERATED Support: NO Comment: Federated MySQL storage engine *************************** 18. row *************************** Engine: BLACKHOLE Support: YES Comment: /dev/null storage engine (anything you write to it disappears)
Support值指示某个存储引擎是否被支持,并指示哪个是默认引擎。例如,如果服务器以--default-table-type=InnoDB选项为起始,åˆ�InnoDB行的Support值为DEFAULT值。请参见ç¬�15章:存储引擎和表类型ã€�
SHOW ERRORS [LIMIT [offset,] row_count]
SHOW COUNT(*) ERRORS
本语句与SHOW WARNINGS接近,不过该语句只显示错误,不同时显示错误、警告和注意ã€�
LIMIT子句ä¸�SELECT语句具有相同的语法,请参è§�13.2.7节,“SELECT语法â€�ã€�
SHOW COUNT(*) ERRORS语句显示错误的数目。您也可以从error_count变量中找回此数目ï¼�
SHOW COUNT(*) ERRORS;
SELECT @@error_count;
要了解更多信息,请参è§�13.5.4.22节,“SHOW WARNINGS语法â€�ã€�
SHOW GRANTS FOR user
本语句列出了在为MySQL用户账户复制权限时必须发布的GRANT语句ã€�
mysql> SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
要对当前的会话列出权限,您可以使用以下语句之一ï¼�
SHOW GRANTS;
SHOW GRANTS FOR CURRENT_USER;
SHOW GRANTS FOR CURRENT_USER();
SHOW INDEX FROM tbl_name [FROM db_name]
SHOW INDEX会返回表索引信息。其格式ä¸�ODBC中的SQLStatistics调用相似ã€�
SHOW INDEX会返回以下字段:
· Table
表的名称ã€�
· Non_unique
如果索引不能包括重复词,则为0。如果可以,则为1ã€�
· Key_name
索引的名称ã€�
· Seq_in_index
索引中的列序列号,从1开始ã€�
· Column_name
列名称ã€�
· Collation
列以什么方式存储在索引中。在MySQL中,有值â€�A’(升序)或NULL(无分类)ã€�
· Cardinality
索引中唯一值的数目的估计值。通过运行ANALYZE TABLEæˆ�myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时ï¼�MySQL使用该索引的机会就越大ã€�
· Sub_part
如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则ä¸�NULLã€�
· Packed
指示关键字如何被压缩。如果没有被压缩,则ä¸�NULLã€�
· Null
如果列含æœ�NULL,则含有YES。如果没有,则该列含æœ�NOã€�
· Index_type
用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)ã€�
· Comment
多种评注ã€�
您可以使ç”�db_name.tbl_name作为tbl_name FROM db_name语法的另一种形式。这两个语句是等价的ï¼�
mysql> SHOW INDEX FROM mytable FROM mydb;
mysql> SHOW INDEX FROM mydb.mytable;
SHOW KEYSæ˜�SHOW INDEX的同义词。您也可以使ç”�mysqlshow -k db_name tbl_name命令列举一个表的索引ã€�
SHOW INNODB STATUS
åœ�MySQL 5.1中,这是SHOW ENGINE INNODB STATUS的同义词,但不赞成使用。请参见13.5.4.7节,“SHOW ENGINE语法â€�ã€�
SHOW [BDB] LOGS
åœ�MySQL 5.1中,这是SHOW ENGINE BDB LOGS的同义词,但是不赞成使用。请参见13.5.4.7节,“SHOW ENGINE语法â€�ã€�
SHOW OPEN TABLES [FROM db_name] [LIKE 'pattern']
SHOW OPEN TABLES列举在表缓存中当前被打开的非TEMPORARY表。请参见7.4.9节,“MySQL如何打开和关闭表â€�ã€�
SHOW OPEN TABLES会返回以下字段:
· Database
含有该表的数据库ã€�
· Table
表名称ã€�
· In_use
表当前被查询使用的次数。如果该数为零,则表是打开的,但是当前没有被使用ã€�
· Name_locked
表名称是否被锁定。名称锁定用于取消表或对表进行重命名等操作ã€�
SHOW PRIVILEGES
SHOW PRIVILEGES显示MySQL服务器支持的系统权限清单。确切的输出根据您的服务器的版本而定ã€�
mysql> SHOW PRIVILEGES\G
*************************** 1. row ***************************
Privilege: Alter
Context: Tables
Comment: To alter the table
*************************** 2. row ***************************
Privilege: Alter routine
Context: Functions,Procedures
Comment: To alter or drop stored functions/procedures
*************************** 3. row ***************************
Privilege: Create
Context: Databases,Tables,Indexes
Comment: To create new databases and tables
*************************** 4. row ***************************
Privilege: Create routine
Context: Functions,Procedures
Comment: To use CREATE FUNCTION/PROCEDURE
*************************** 5. row ***************************
Privilege: Create temporary tables
Context: Databases
Comment: To use CREATE TEMPORARY TABLE
*************************** 6. row ***************************
Privilege: Create view
Context: Tables
Comment: To create new views
*************************** 7. row ***************************
Privilege: Create user
Context: Server Admin
Comment: To create new users
*************************** 8. row ***************************
Privilege: Delete
Context: Tables
Comment: To delete existing rows
*************************** 9. row ***************************
Privilege: Drop
Context: Databases,Tables
Comment: To drop databases, tables, and views
*************************** 10. row ***************************
Privilege: Execute
Context: Functions,Procedures
Comment: To execute stored routines
*************************** 11. row ***************************
Privilege: File
Context: File access on server
Comment: To read and write files on the server
*************************** 12. row ***************************
Privilege: Grant option
Context: Databases,Tables,Functions,Procedures
Comment: To give to other users those privileges you possess
*************************** 13. row ***************************
Privilege: Index
Context: Tables
Comment: To create or drop indexes
*************************** 14. row ***************************
Privilege: Insert
Context: Tables
Comment: To insert data into tables
*************************** 15. row ***************************
Privilege: Lock tables
Context: Databases
Comment: To use LOCK TABLES (together with SELECT privilege)
*************************** 16. row ***************************
Privilege: Process
Context: Server Admin
Comment: To view the plain text of currently executing queries
*************************** 17. row ***************************
Privilege: References
Context: Databases,Tables
Comment: To have references on tables
*************************** 18. row ***************************
Privilege: Reload
Context: Server Admin
Comment: To reload or refresh tables, logs and privileges
*************************** 19. row ***************************
Privilege: Replication client
Context: Server Admin
Comment: To ask where the slave or master servers are
*************************** 20. row ***************************
Privilege: Replication slave
Context: Server Admin
Comment: To read binary log events from the master
*************************** 21. row ***************************
Privilege: Select
Context: Tables
Comment: To retrieve rows from table
*************************** 22. row ***************************
Privilege: Show databases
Context: Server Admin
Comment: To see all databases with SHOW DATABASES
*************************** 23. row ***************************
Privilege: Show view
Context: Tables
Comment: To see views with SHOW CREATE VIEW
*************************** 24. row ***************************
Privilege: Shutdown
Context: Server Admin
Comment: To shut down the server
*************************** 25. row ***************************
Privilege: Super
Context: Server Admin
Comment: To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
*************************** 26. row ***************************
Privilege: Update
Context: Tables
Comment: To update existing rows
*************************** 27. row ***************************
Privilege: Usage
Context: Server Admin
Comment: No privileges - allow connect only
SHOW [FULL] PROCESSLIST
SHOW PROCESSLIST显示哪些线程正在运行。您也可以使ç”�mysqladmin processlist语句得到此信息。如果您æœ�SUPER权限,您可以看到所有线程。否则,您只能看到您自己的线程(也就是,与您正在使用çš�MySQL账户相关的线程)。请参见13.5.5.3节,“KILL语法â€�。如果您不使ç”�FULL关键词,则只显示每个查询的前100个字符ã€�
本语句报å‘�TCP/IP连接的主机名称(采用host_name:client_port格式),以方便地判定哪个客户端正在做什么ã€�
如果您得到â€�too many connections”错误信息,并且想要了解正在发生的情况,本语句是非常有用的ã€�MySQL保留一个额外的连接,让拥有SUPER权限çš� 账户使用,以确保管理员能够随时连接和检查系统(假设您没有把此权限给予所有的用户)ã€�
在来è‡�SHOW PROCESSLIST的输出中常见的一些状态:
· Checking table
线程正在执行(自动)表格检查ã€�
· Closing tables
意味着线程正在刷新更改后的表数据,并正在关闭使用过的表。这应该是一个快速的操作。如果不快,则您应该验证您的磁盘没有充满,并且磁盘没有被超负荷使用ã€�
· Connect Out
连接到主服务器上的从属服务器ã€�
· Copying to tmp table on disk
临时结果集合大于tmp_table_size。线程把临时表从存储器内部格式改变为磁盘模式,以节约存储器ã€�
· Creating tmp table
线程正在创建一个临时表,以保持部分结果ã€�
· deleting from main table
服务器正在执行多表删除的第一部分,只从第一个表中删除ã€�
· deleting from reference tables
服务器正在执行多表删除的第二部分,从其它表中删除匹配的行ã€�
· Flushing tables
线程正在执行FLUSH TABLES,并正在等待所有线程,以关闭表ã€�
· FULLTEXT initialization
服务器正在准备执行一个自然语言全文本搜紀€�
· Killed
有人已经向线程发送了一ä¸�KILL命令。在下一次检查终止标记时,应放弃。该标记åœ�MySQL的每个大循环中都检查,但是在有些情况下,线程终止只需要较短的时间。如果该线程被其它线程锁定,则只要其它线程接触锁定,终止操作就会生效ã€�
· Locked
该查询被其它查询锁定ã€�
· Sending data
线程正在ä¸�SELECT语句处理行,同时正在向客户端发送数据ã€�
· Sorting for group
线程正在进行分类,以满足GROUP BY要求ã€�
· Sorting for order
线程正在进行分类,以满足ORDER BY要求ã€�
· Opening tables
线程正在试图打开一个表。这应该是非常快的过程,除非打开操作受到阻止。例如,一ä¸�ALTER TABLE或一ä¸�LOCK TABLE语句可以阻止打开一个表,直到语句完成为歀€�
· Removing duplicates
查询正在使用SELECT DISTINCT。使用时,在早期阶段ï¼�MySQL不能优化不同的操作。因此,MySQL要求一个额外的阶段,以便在把结果发送给客户端之前取消所有的复制行ã€�
· Reopen table
线程得到一个表锁定,但是在得到锁定后被通知带下方的表结构已更改了。它已经释放了锁定,关闭了表,并试图重新打开它ã€�
· Repair by sorting
修复代码正在使用一个分类来创建索引ã€�
· Repair with keycache
修复代码正在通过关键缓存一个接一个地使用创建关键字。这比通过分类修复要慢很多ã€�
· Searching rows for update
线程正在进行第一阶段,以在更新之前,查找所有匹配的行。如æž�UPDATE正在更改用于查找相关行的索引,则必须这么做ã€�
· Sleeping
线程正在等待客户端,以向它发送一个新语句ã€�
· System lock
线程正在等待得到一个用于表的外部系统锁定。如果您没有正在使用多个正在访问同一个表çš�mysqld服务器,则您可以使用--skip-external-locking选项禁用系统锁定ã€�
· Upgrading lock
INSERT DELAYED管理程序正在试图得到一个表锁定,以插入行ã€�
· Updating
线程正在搜索行,并正在更新这些行ã€�
· User Lock
线程正在等待GET_LOCK()ã€�
· Waiting for tables
线程得到一个通知,表的底层结构已经改变,需要重新打开表以得到新的结构。但是,为了能重新打开表,必须等待,直到所有其它的线程已经关闭了正在被质询的表ã€�
如果其它线程已经对正在被质询的表使用äº�FLUSH TABLES或以下语句之一ï¼�FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLEæˆ�OPTIMIZE TABLE;则会出现通知ã€�
· waiting for handler insert
INSERT DELAYED管理程序已经处理了所有处于等待状态的插入,并正在等待新插入ã€�
多数状态对应于非常快的操作。如果一个线程在这些状态下停留了数秒,则可能是有问题,需要进行调查ã€�
有一些其它的状态,在前面的清单中没有提及,但是其中有很多状态对于查找服务器中的程序错误是有用的ã€�
SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']
SHOW STATUS提供服务器状态信息。此信息也可以使ç”�mysqladmin extended-status命令获得ã€�
此处显示了局部的输出。对于您的服务器,变量和值的清单可以是不同的。在5.3.4节,“服务器状态变量â€�中给出了每个变量的意义ã€�
mysql> SHOW STATUS;
+--------------------------+------------+
| Variable_name | Value |
+--------------------------+------------+
| Aborted_clients | 0 |
| Aborted_connects | 0 |
| Bytes_received | 155372598 |
| Bytes_sent | 1176560426 |
| Connections | 30023 |
| Created_tmp_disk_tables | 0 |
| Created_tmp_tables | 8340 |
| Created_tmp_files | 60 |
... ... ...
| Open_tables | 1 |
| Open_files | 2 |
| Open_streams | 0 |
| Opened_tables | 44600 |
| Questions | 2026873 |
... ... ...
| Table_locks_immediate | 1920382 |
| Table_locks_waited | 0 |
| Threads_cached | 0 |
| Threads_created | 30022 |
| Threads_connected | 1 |
| Threads_running | 1 |
| Uptime | 80380 |
+--------------------------+------------+
使用LIKE子句,该语句只显示匹配该样式的那些变量:
mysql> SHOW STATUS LIKE 'Key%';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| Key_blocks_used | 14955 |
| Key_read_requests | 96854827 |
| Key_reads | 162040 |
| Key_write_requests | 7589728 |
| Key_writes | 3813196 |
+--------------------+----------+
使用GLOBAL选项,您可以得到所æœ�MySQL连接的状态值。使ç”�SESSION,您可以得到所有当前连接的状态值。如果您两个选项都不使用,则默认值为SESSIONã€�LOCALæ˜�SESSION的同义词ã€�
注意,有些状态变量只有一个全局值。对于这些变量,使用GLOBALå’�SESSION会得到同样的值ã€�
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
SHOW TABLE STATUS的性质ä¸�SHOW TABLE类似,不过,可以提供每个表的大量信息。您也可以使ç”�mysqlshow --status db_name命令得到此清单ã€�
本语句也显示视图信息ã€�
对于NDB Cluster表,本语句的输出显示Avg_row_lengthå’�Data_length列的适当值,不过BLOB列没有被考虑进来。另外,复制数量åœ�Comment列中显示(作ä¸�number_of_replicas)ã€�
SHOW TABLE STATUS会返回以下字段:
· Name
表的名称ã€�
· Engine
表的存储引擎。在MySQL 4.1.2之前,本值被标记ä¸�Type。请参见ç¬�15章:存储引擎和表类型ã€�
· Version
表的.frm文件的版本号ã€�
· Row_format
行存储格式(Fixed, Dynamic, Compressed, Redundant, Compact)ã€�InnoDB表的格式被报告为Redundantæˆ�Compactã€�
· Rows
行的数目。部分存储引擎,å¦�MyISAM,存储精确的数目ã€�
对于其它存储引擎,比å¦�InnoDB,本值是一个大约的数,与实际值相差可è¾�40åˆ�50%。在这些情况下,使用SELECT COUNT(*)来获得准确的数目ã€�
对于åœ�INFORMATION_SCHEMA数据库中的表ï¼�Rows值为NULLã€�
· Avg_row_length
平均的行长度ã€�
· Data_length
数据文件的长度ã€�
· Max_data_length
数据文件的最大长度。如果给定了数据指针的大小,这是可以被存储在表中的数据的字节总数ã€�
· Index_length
索引文件的长度ã€�
· Data_free
被整序,但是未使用的字节的数目ã€�
· Auto_increment
下一ä¸�AUTO_INCREMENT值ã€�
· Create_time
什么时候表被创建ã€�
· Update_time
什么时候数据文件被最后一次更新ã€�
· Check_time
什么时候表被最后一次检查。不是所有的存储引擎此时都更新,在此情况下,值为NULLã€�
· Collation
表的字符集和整序ã€�
· Checksum
活性校验和值ã€�
· Create_options
å’�CREATE TABLE同时使用的额外选项ã€�
· Comment
创建表时使用的评注(或者有关为什ä¹�MySQL可以访问表信息的说明)ã€�
在表评注中,InnoDB表报告表所属的表空间的空闲空间。对于一个位于共享表空间中的表,这是共享表空间中的空闲空间。如果您正在使用多个表空间,并且该表有自己的表空间,则空闲空间只用于此表ã€�
对于MEMORY (HEAP)表,Data_length, Max_data_lengthå’�Index_length值近似于被整序的存储器的实际值。整序算法预留了大量的存储器,以减少整序操作的数量ã€�
对于视图,由SHOW TABLE STATUS显示的所有字段均ä¸�NULL。例外情况是Name指示为视图名称同æ—�Comment称为视图ã€�
SHOW [FULL] TABLES [FROM db_name] [LIKE 'pattern']
SHOW TABLES列举了给定数据库中的é��TEMPORARY表。您也可以使ç”�mysqlshow db_name命令得到此清单ã€�
本命令也列举数据库中的其它视图。支æŒ�FULL修改符,这样SHOW FULL TABLES就可以显示第二个输出列。对于一个表,第二列的值为BASE TABLE;对于一个视图,第二列的值为VIEWã€�
注释:如果您对于一个表没有权限,则该表不会在来è‡�SHOW TABLES或的mysqlshow db_name输出中显示ã€�
SHOW TRIGGERS [FROM db_name] [LIKE expr]
SHOW TRIGGERS列出了目前被MySQL服务器定义的触发程序ã€�
对于åœ�21.3节,“使用触发程序â€�中定义的触发程序ins_sum,本语句的输出显示如下:
mysql> SHOW TRIGGERS LIKE 'acc%';
+---------+--------+---------+-------------------------------+--------+---------+
| Trigger | Event | Table | Statement | Timing | Created |
+---------+--------+---------+-------------------------------+--------+---------+
| ins_sum | INSERT | account | SET @sum = @sum + NEW.amount | BEFORE | NULL |
+---------+--------+---------+-------------------------------+--------+---------+
注释:当使用一个含æœ�SHOW TRIGGERSçš�LIKE子句时,待匹配的表达式(expr)会与触发程序定义时所在的表的名称相比较,而不与触发程序的名称相比较:
mysql> SHOW TRIGGERS LIKE 'ins%';
Empty set (0.01 sec)
对本语句输出中的各列的简要解释如下:
· Trigger: 触发程序的名称ã€�
· Event: 调用触发程序的时间。必须为'INSERT', 'UPDATE'æˆ� 'DELETE'.之一ã€�
· Table: 触发程序定义时对应的表ã€�
· Statement: 当触发程序被调用时执行的语句。这与在INFORMATION_SCHEMA.TRIGGERSçš�ACTION_STATEMENT列中显示的文本一样ã€�
· Timing: 'BEFORE'æˆ�'AFTER'两个值之一ã€�
· Created: 目前,本列的值为NULLã€�
为了执行SHOW TRIGGERS,您必须拥有SUPER权限ã€�
SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
SHOW VARIABLES显示了部é—�MySQL系统变量的值。本信息也可以使ç”�mysqladmin variables命令获得ã€�
使用GLOBAL选项,您可以获得被用äº�MySQL新连接的值。使ç”�SESSION,您可以得到对于当前连接起效的值。如果您两个选项都不使用,默认值为SESSIONã€�
LOCALæ˜�SESSION的同义词ã€�
如果默认值不合适,å½�mysqld启动时或åœ�SET语句运行过程中,您可以使用命令行选项设置多数的这类变量。请参见5.3.1节,â€�mysqld命令行选项â€�å’�13.5.3节,“SET语法ã€�
此处显示了部分的输出。对于您的服务器,变量和值的清单会有所不同。在5.3.3节,“服务器系统变量â€�中给出了每个变量的意义。在7.5.2节,“调节服务器参数â€�中提供了有关调整变量的信息ã€�
mysql> SHOW VARIABLES;
+---------------------------------+-----------------------------------------------+
| Variable_name | Value |
+---------------------------------+-----------------------------------------------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| automatic_sp_privileges | ON |
| back_log | 50 |
| basedir | /home/jon/bin/mysql-5.1/ |
| binlog_cache_size | 32768 |
| bulk_insert_buffer_size | 8388608 |
| character_set_client | latin1 |
| character_set_connection | latin1 |
... ...
| max_user_connections | 0 |
| max_write_lock_count | 4294967295 |
| multi_range_count | 256 |
| myisam_data_pointer_size | 6 |
| myisam_max_sort_file_size | 2147483647 |
| myisam_recover_options | OFF |
| myisam_repair_threads | 1 |
| myisam_sort_buffer_size | 8388608 |
| ndb_autoincrement_prefetch_sz | 32 |
| ndb_cache_check_time | 0 |
| ndb_force_send | ON |
... ... ...
| time_zone | SYSTEM |
| timed_mutexes | OFF |
| tmp_table_size | 33554432 |
| tmpdir | |
| transaction_alloc_block_size | 8192 |
| transaction_prealloc_size | 4096 |
| tx_isolation | REPEATABLE-READ |
| updatable_views_with_limit | YES |
| version | 5.1.2-alpha-log |
| version_comment | Source distribution |
| version_compile_machine | i686 |
| version_compile_os | suse-linux |
| wait_timeout | 28800 |
+---------------------------------+-----------------------------------------------+
使用LIKE子句,本语句只显示与样式相匹配的变量ï¼�
mysql> SHOW VARIABLES LIKE 'have%';
+-----------------------+----------+
| Variable_name | Value |
+-----------------------+----------+
| have_archive | YES |
| have_bdb | NO |
| have_blackhole_engine | YES |
| have_compress | YES |
| have_crypt | YES |
| have_csv | YES |
| have_example_engine | NO |
| have_federated_engine | NO |
| have_geometry | YES |
| have_innodb | YES |
| have_isam | NO |
| have_ndbcluster | DISABLED |
| have_openssl | NO |
| have_partition_engine | YES |
| have_query_cache | YES |
| have_raid | NO |
| have_rtree_keys | YES |
| have_symlink | YES |
+-----------------------+----------+
SHOW WARNINGS [LIMIT [offset,] row_count]
SHOW COUNT(*) WARNINGS
SHOW WARNINGS显示由上一个生成消息的语句导致的错误、警告和注意消息。如果上一个使用表的语句未生成消息,则什么也不显示ã€�SHOW ERRORS是其相关语句,只显示错误。请参见13.5.4.9节,“SHOW ERRORS语法â€�ã€�
对于使用一个表的每个新语句,消息清单均重新设置ã€�
SHOW COUNT(*) WARNINGS语句显示错误、警告和注意的总数。您也可以从warning_count变量中找回此数目ã€�
SHOW COUNT(*) WARNINGS;
SELECT @@warning_count;
如果max_error_count系统变量设置得过低,以致于有的消息没有被存储,则warning_count值可能比ç”�SHOW WARNINGS显示的消息数目要大。本节后部显示的例子展示了这类情况是如何发生的ã€�
LIMIT子句具有ä¸�SELECT语句相同的语法。请参见13.2.7节,“SELECT语法â€�ã€�
MySQL服务器会发回由上一个语句引起的错误、警告和注意的总数。如果您正在使用C API,则此值可以通过调用mysql_warning_count()来获得。请参见25.2.3.69节,“mysql_warning_count()â€�ã€�
对于å¦�LOAD DATA INFILE等语句和å¦�INSERT, UPDATE, CREATE TABLEå’�ALTER TABLEç�DML语句,会生成警告ã€�
以下DROP TABLE语句会导致一个注意:
mysql> DROP TABLE IF EXISTS no_such_table;
mysql> SHOW WARNINGS;
+-------+------+-------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------+
| Note | 1051 | Unknown table 'no_such_table' |
+-------+------+-------------------------------+
以下是一个简单的例子,显示了对于CREATE TABLE的一个语法警告,和对äº�INSERT的转换警告:
mysql> CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4)) TYPE=MyISAM;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Warning
Code: 1287
Message: 'TYPE=storage_engine' is deprecated, use
'ENGINE=storage_engine' instead
1 row in set (0.00 sec)
mysql> INSERT INTO t1 VALUES(10,'mysql'),(NULL,'test'),
-> (300,'Open Source');
Query OK, 3 rows affected, 4 warnings (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 4
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Warning
Code: 1265
Message: Data truncated for column 'b' at row 1
*************************** 2. row ***************************
Level: Warning
Code: 1263
Message: Data truncated, NULL supplied to NOT NULL column 'a' at row 2
*************************** 3. row ***************************
Level: Warning
Code: 1264
Message: Data truncated, out of range for column 'a' at row 3
*************************** 4. row ***************************
Level: Warning
Code: 1265
Message: Data truncated for column 'b' at row 3
4 rows in set (0.00 sec)
要存储的错误、警告和注意消息的最大数目由max_error_count系统变量控制。默认情况下,该值为64。要更改您想要存储的信息的数目,需更改max_error_count值。在下面的例子中ï¼�ALTER TABLE语句会产生三个警告消息,但是只有一个被存储,因ä¸�max_error_count被设置为1ï¼�
mysql> SHOW VARIABLES LIKE 'max_error_count';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_error_count | 64 |
+-----------------+-------+
1 row in set (0.00 sec)
mysql> SET max_error_count=1;
Query OK, 0 rows affected (0.00 sec)
mysql> ALTER TABLE t1 MODIFY b CHAR;
Query OK, 3 rows affected, 3 warnings (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 3
mysql> SELECT @@warning_count;
+-----------------+
| @@warning_count |
+-----------------+
| 3 |
+-----------------+
1 row in set (0.01 sec)
mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1263 | Data truncated for column 'b' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
要禁用警告,需æŠ�max_error_count设置ä¸�0。在此情况下ï¼�warning_count仍然指示有多少警告已经发生,但是这些消息不被存储ã€�
您可以把SQL_NOTES会话变量设置ä¸�0,使“注意”级别的警告不被记录ã€�
CACHE INDEX
tbl_index_list [, tbl_index_list] ...
IN key_cache_name
tbl_index_list:
tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]
CACHE INDEX语句把表索引分配给某个关键缓存。该语句只用äº�MyISAM表ã€�
下列语句把索引从è¡�t1, t2å’�t3分配到名ä¸�hot_cache的关键缓存:
mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status | OK |
| test.t2 | assign_to_keycache | status | OK |
| test.t3 | assign_to_keycache | status | OK |
+---------+--------------------+----------+----------+
CACHE INDEX语法允许您指定,只有来自表的特定索引应被分配给缓存。但是,当前的实施会把所有的表索引分配给缓存,所以必须指定表名称,不能指定其它的ã€�
被引用到CACHE INDEX语句中的关键缓存可以这样创建,即通过使用一个参数设置语句或在服务器参数设置中设置其大小。举例说明:
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
关键缓存参数可以被作为一个结构化系统变量的成分进行访问。请参见9.4.1节,“结构式系统变量â€�ã€�
在您可以把索引分配给一个关键缓存以前,缓存必须存在ï¼�
mysql> CACHE INDEX t1 IN non_existent_cache;
ERROR 1284 (HY000): Unknown key cache 'non_existent_cache'
默认情况下,表索引被分配给在服务器启动时被创建的主(默认)键缓存。当一个键高速缓冲被破坏时,所有被分配到此缓存中的索引会再次被分配给默认的 键高速缓冲ã€�
索引的分配会对服务器产生全局性影响:如果一个客户端把一个索引分配给一个给定的缓存,则不论什么客户端发布查询,本缓存都被用于所有涉及索引的查询ã€�
FLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ...
如果您想要清é™�MySQL使用的部分内部缓存,您应该使ç”�FLUSH语句。要执行FLUSH,您必须拥有RELOAD权限ã€�
flush_option可以为以下的任何一个:
· HOSTS
用于清空主机缓存表。如果有的主机更改了IP号或如果您得到了错误信息Host host_name is blocked,则您应该刷新主机表。当在连接到MySQL服务器时,如果对于一个给定的主机,接连出现错误“多äº�max_connect_errors”,此时ï¼�MySQL会假定出现了错误,并阻止主机后续的连接申请。刷新主机表允许主机尝试再次连接。请参见A.2.5节,“主机的host_name被屏è”�â€�。您可以使用max_connect_errors=999999999启动mysqld,以避免此错误信息ã€�
· DES_KEY_FILE
用于在服务器启动时,从采ç”�--des-key-file选项指定的文件重新载å…�DES关键字ã€�
· LOGS
用于关闭并重新打开所有的日志文件。如果您已经指定了一个更新日志文件或一个二进制日志文件,同时没有扩展,则相对于前一个文件,日志文件的扩展号增加1。如果您在文件名称中使用了一个扩展,åˆ�MySQL会关闭并重新打开日志文件。在Unix中,当相mysqld服务器发送一ä¸�SIGHUP信号时,也会如此(例外情况是部分Mac OS X 10.3版本。在这些版本中,mysqld忽略SIGHUPå’�SIGQUIT)ã€�
如果服务器使ç”�--log-error选项,则FLUSH LOGS会导致错误日志被重命名(使用后缀-old),同时mysqld会创建一个新的空日志文件。如果没有给å®�--log-error选项,则不会进行重命名ã€�
· PRIVILEGES
用于ä»�mysql数据库中的授权表重新载入权限ã€�
· QUERY CACHE
对查询缓存进行整理碎片,以更好得利用存储器。与RESET QUERY CACHE不同,本语句不会从缓存中取消任何查询ã€�
· STATUS
用于把多数状态变量重新设置为零。只在当调试查询时,您才应该使用此项。请参见1.7.1.3节,“如何通报缺陷和问题â€�ã€�
· {TABLE | TABLES} [tbl_name [, tbl_name] ...]
当没有表被命名时,关闭所有打开的表,并迫使所有正在使用的表关闭。这也会刷新查询缓存。此项含有一个或多个表名称,只刷新给定的表。和RESET QUERY CACHE语句一样,FLUSH TABLES还会取消来自查询缓存的所有查询结果ã€�
· TABLES WITH READ LOCK
对于所有带读取锁定的数据库,关闭所有打开的表,并锁定所有的表,直到您执è¡�UNLOCK TABLES为止。如果您拥有一个可以及时进行快照的文件系统,比å¦�Veritas,则这是进行备份的非常方便的方法ã€�
· USER_RESOURCES
用于把所有每小时用户资源重新设置为零。这可以使已经达到了每小时连接、查询或更新限值的客户端立刻重新恢复活性ã€�FLUSH USER_RESOURCES不适用于同时连接的最大限值。请参见13.5.1.3节,“GRANT和REVOKE语法â€�ã€�
FLUSH语句被写入二进制日志,除非使用了自选的NO_WRITE_TO_BINLOG关键字(或其别名LOCAL)ã€� 注释:在任何情况下,FLUSH LOGS, FLUSH MASTER, FLUSH SLAVEå’�FLUSH TABLES WITH READ LOCK都不会被记入日志,因为如果它们被复制到一个从属服务器上,会导致出现问题ã€�
您也可以使用flush-hosts, flush-logs, flush-privileges, flush-statusæˆ�flush-tables命令访问含有mysqladmin应用程序的语句ã€�
注释:在MySQL 5.1.2-alpha中,不可能在已存储的函数或触发程序中发布FLUSH语句。不过,您可以在已存储的过程中使ç”�FLUSH,只要它们不会从已存储的函数或触发程序中被调用。请参见I.1节,“对存储子程序和触发程序的限制â€�ã€�
要了解有å…�RESET语句与复制同时使用的信息,也可以è§�13.5.5.5节,“RESET语法â€�ã€�
KILL [CONNECTION | QUERY] thread_id
每个ä¸�mysqld的连接都在一个独立的线程里运行,您可以使ç”�SHOW PROCESSLIST语句查看哪些线程正在运行,并使用KILL thread_id语句终止一个线程ã€�
KILL允许自选的CONNECTIONæˆ�QUERY修改符:
· KILL CONNECTION与不含修改符çš�KILL一样:它会终止与给定的thread_id有关的连接ã€�
· KILL QUERY会终止连接当前正在执行的语句,但是会保持连接的原状ã€�
如果您拥æœ�PROCESS权限,则您可以查看所有线程。如果您拥有SUPER权限,您可以终止所有线程和语句。否则,您只能查看和终止您自己的线程和语句ã€�
您也可以使用mysqladmin processlistå’�mysqladmin kill命令来检查和终止线程ã€�
注释:您不能同时使用KILLå’�Embedded MySQL Server库,因为内植的服务器只运行主机应用程序的线程。它不能创建任何自身的连接线程ã€�
当您进行一ä¸�KILL时,对线程设置一个特有的终止标记。在多数情况下,线程终止可能要花一些时间,这是因为终止标记只会在在特定的间隔被检查:
· åœ�SELECT, ORDER BYå’�GROUP BY循环中,在读取一组行后检查标记。如果设置了终止标记,则该语句被放弃ã€�
· åœ�ALTER TABLE过程中,在每组行从原来的表中被读取前,检查终止标记。如果设置了终止标记,则语句被放弃,临时表被删除ã€�
· åœ�UPDATEæˆ�DELETE运行期间,在每个组读取之后以及每个已更行或已删除的行之后,检查终止标记。如果终止标记被设置,则该语句被放弃。注意,如果您正在使用事务,则变更不会被 回滚ã€�
· GET_LOCK()会放弃和返回NULLã€�
· INSERT DELAYED线程会快速地刷新(插入)它在存储器中的所有的行,然后终止ã€�
· 如果线程在表锁定管理程序中(状态:锁定),则表锁定被快速地放弃ã€�
· 如果在写入调用中,线程正在等待空闲的磁盘空间,则写入被放弃,并伴éš�"disk full"错误消息ã€�
· 警告:对MyISAM表终止一ä¸�REPAIR TABLEæˆ�OPTIMIZE TABLE操作会导致出现一个被损坏的没有用的表。对这样的表的任何读取或写入都会失败,直到您再次优化或修复它(不中断)ã€�
LOAD INDEX INTO CACHE
tbl_index_list [, tbl_index_list] ...
tbl_index_list:
tbl_name
[[INDEX|KEY] (index_name[, index_name] ...)]
[IGNORE LEAVES]
LOAD INDEX INTO CACHE语句会把一个表索引预载入到某个关键缓存中。它已经被一个明确的CACHE INDEX语句分配到此关键缓存中。或者,表索引被预载入到默认的关键缓存中ã€�LOAD INDEX INTO CACHE只用äº�MyISAM表ã€�
IGNORE LEAVES修改符只会导致索引的非叶子节点被预载入ã€�
对于è¡�t1å’�t2,以下语句会预载入索引的节点(索引组):
mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status | OK |
| test.t2 | preload_keys | status | OK |
+---------+--------------+----------+----------+
本语句会预载入所有来è‡�t1的索引组。它只预载入来自t2的非叶子节点的组ã€�
LOAD INDEX INTO CACHE语法允许您指定,只有来自表的特定的索引应被预载入。但是,当前实施会把所有的表索引预载入缓存中,所以一定要指定表名称,不能指定其它的ã€�
RESET reset_option [, reset_option] ...
RESET语句被用于清除不同的服务器操作的状态。它也作ä¸�FLUSH语句的更强大的版本。请参见13.5.5.2节,“FLUSH语法â€�ã€�
为了执行RESET,您必须拥有RELOAD权限ã€�
reset_option可以为以下的任何一项:
· MASTER
可以删除列于索引文件中的所有二进制日志,把二进制日志索引文件重新设置为空,并创建一个新的二进制日志文件。(在以前版本的MySQL中,被称ä¸�FLUSH MASTER。)è§�13.6.1节,“用于控制主服务器的SQL语句â€�ã€�
· QUERY CACHE
从查询缓存中取消所有的查询结果ã€�
· SLAVE
可以使从属服务器忘记其在主服务器二进制日志中的复制位置,另外,也可以通过删除原有的中继日志文件和开始一个新文件来重新设置中继日志。请参见13.6.2节,“用于控制从服务器的SQL语句â€�ã€�
可以通过SQL界面控制复制。本节讨论了用于管理主复制服务器的语句ã€�13.6.2节,“用于控制从服务器的SQL语句â€�讨论了用于管理从属服务器的语句ã€�
PURGE {MASTER | BINARY} LOGS TO 'log_name'
PURGE {MASTER | BINARY} LOGS BEFORE 'date'
用于删除列于在指定的日志或日期之前的日志索引中的所有二进制日志。这些日志也会从记录在日志索引文件中的清单中被删除,这样被给定的日志成为第一个ã€�
例如ï¼�
PURGE MASTER LOGS TO 'mysql-bin.010';
PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';
BEFORE变量çš�date自变量可以为'YYYY-MM-DD hh:mm:ss'格式ã€�MASTERå’�BINARY是同义词ã€�
如果您有一个活性的从属服务器,该服务器当前正在读取您正在试图删除的日志之一,则本语句不会起作用,而是会失败,并伴随一个错误。不过,如果从属服务器是休止的,并且您碰巧清理了其想要读取的日志之一,则从属服务器启动后不能复制。当从属服务器正在复制时,本语句可以安全运行。您不需要停止它们ã€�
要清理日志,需按照以下步骤ï¼�
1. 在每个从属服务器上,使用SHOW SLAVE STATUS来检查它正在读取哪个日志ã€�
2. 使用SHOW MASTER LOGS获得主服务器上的一系列日志ã€�
3. 在所有的从属服务器中判定最早的日志。这个是目标日志。如果所有的从属服务器是更新的,这是清单上的最后一个日志ã€�
4. 制作您将要删除的所有日志的备份。(这个步骤是自选的,但是建议采用。)
5. 清理所有的日志,但是不包括目标日志ã€�
SHOW BINLOG EVENTS
[IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
用于在二进制日志中显示事件。如果您不指å®�'log_name',则显示第一个二进制日志ã€�
LIMIT子句å’�SELECT语句具有相同的语法。请参见13.2.7节,“SELECT语法â€�ã€�
注释:当æœ�务器把二进制日志的完整内容(该日志包括多数的ç”�MySQL执行的查询)转储åˆ�stdout时,发布一个不å��LIMIT子句çš�SHOW BINLOG EVENTS可以启动一个过程,该过程非常消耗时间并消耗资æº�。要把二进制日志保存到一个文本文件中,用于以后的检查和分析,需使用mysqlbinlog应用程序。请参见8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具â€�ã€�
SHOW MASTER LOGS
SHOW BINARY LOGS
用于列出服务器中的二进制日志文件。本语句被用ä½�13.6.1.1节,“PURGE MASTER LOGS语法â€�中所述的过程的一部分,用于确定哪些日志可以被清理ã€�
mysql> SHOW BINARY LOGS;
+---------------+-----------+
| Log_name | File_size |
+---------------+-----------+
| binlog.000015 | 724935 |
| binlog.000016 | 733481 |
+---------------+-----------+
SHOW BINARY LOGSä¸�SHOW MASTER LOGS相当ã€�
SHOW MASTER STATUS
用于提供主服务器二进制日志文件的状态信息。例如:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
复制操作可以通过SQL界面控制。本节讨论了用于管理从属复制服务器的语句ã€�13.6.1节,“用于控制主服务器的SQL语句â€�讨论了用于管理主服务器的语句ã€�
CHANGE MASTER TO master_def [, master_def] ...
master_def:
MASTER_HOST = 'host_name'
| MASTER_USER = 'user_name'
| MASTER_PASSWORD = 'password'
| MASTER_PORT = port_num
| MASTER_CONNECT_RETRY = count
| MASTER_LOG_FILE = 'master_log_name'
| MASTER_LOG_POS = master_log_pos
| RELAY_LOG_FILE = 'relay_log_name'
| RELAY_LOG_POS = relay_log_pos
| MASTER_SSL = {0|1}
| MASTER_SSL_CA = 'ca_file_name'
| MASTER_SSL_CAPATH = 'ca_directory_name'
| MASTER_SSL_CERT = 'cert_file_name'
| MASTER_SSL_KEY = 'key_file_name'
| MASTER_SSL_CIPHER = 'cipher_list'
可以更改从属服务器用于与主服务器进行连接和通讯的参数ã€�
MASTER_USER, MASTER_PASSWORD, MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEYå’�MASTER_SSL_CIPHER用于向从属服务器提供有关如何与主服务器连接的信息ã€�
即使对于在编译时没有SSL支持的从属服务器ï¼�SSL选项(MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEYå’�MASTER_SSL_CIPHER)也可以被更改。它们被保存åˆ�master.info文件中,但是会被忽略,直到您使用一ä¸�SSL支持已启用的服务器ã€�
如果您不指定一个给定的参数,则它会保持其原有的值。例外情况在后面的讨论中进行了说明。举例说明,如果用于连接到您çš�MySQL主服务器çš� 密码被更改了,您只需发布这些语句,就可以告知从属服务器新的密码:
mysql> STOP SLAVE; -- if replication was running
mysql> CHANGE MASTER TO MASTER_PASSWORD='new3cret';
mysql> START SLAVE; -- if you want to restart replication
没有必要指定没有改变的参数(主机、接口、用户等)ã€�
MASTER_HOSTå’�MASTER_PORT是主服务器主机和å…�TCP/IP接口的主机名(或IP地址)。注意,如果MASTER_HOSTä¸�localhost相等,那么,å’�MySQL的其它部分一样,接口可以被忽略(例如,如果可以使ç”�Unix插槽文件)ã€�
如果您指定了MASTER_HOSTæˆ�MASTER_PORT,则从属服务器会假定主服务器与以前不一样(即使您指定的主机或接口值与当前值是一样的。)在此情况下,主服务器二进制日志的名称和位置的原有值不再适用,因此,如果您不指定语句中的MASTER_LOG_FILEå’�MASTER_LOG_POSï¼�MASTER_LOG_FILE=''å’�MASTER_LOG_POS=4会被静默地添加ã€�
åœ�MASTER_LOG_FILEå’�MASTER_LOG_POS坐标点,从属服务å™�I/O线程在启动之后从主服务器读取。如果您只指定了其中一个,则从属服务器不能指定RELAY_LOG_FILEæˆ�RELAY_LOG_POS。如æž�MSATER_LOG_FILEå’�MASTER_LOG_POS都没有被指定,则从属服务器会使用åœ�CHANGE MASTER被发布前的最后一ä¸�slave SQL thread坐标。当您只想改变要使用çš� 密码时,这可以确保复制的连续性。即使从属服务器SQL线程落后于从属服务器I/O线程,也可以确保复制的连续性ã€�
CHANGE MASTER会删除所有的中继日志文件并启动一个新的日志,除非您指定了RELAY_LOG_FILEæˆ�RELAY_LOG_POS。在此情况下,中继日志被保持ï¼�relay_log_purge全局变量被静默地设置ä¸�0ã€�
CHANGE MASTER TO可以更新master.infoå’�relay-log.info文件的内容ã€�
当您拥有主服务器快照并拥有日志和对应的偏移量时,CHANGE MASTER对于设置从属服务器是有用的。在把快照载入从属服务器之后,您可以在从属服务器上运è¡�CHANGE MASTER TO MASTER_LOG_FILE='log_name_on_master', MASTER_LOG_POS=log_offset_on_masterã€�
举例说明ï¼�
mysql> CHANGE MASTER TO
-> MASTER_HOST='master2.mycompany.com',
-> MASTER_USER='replication',
-> MASTER_PASSWORD='bigs3cret',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='master2-bin.001',
-> MASTER_LOG_POS=4,
-> MASTER_CONNECT_RETRY=10;
mysql> CHANGE MASTER TO
-> RELAY_LOG_FILE='slave-relay-bin.006',
-> RELAY_LOG_POS=4025;
第一个例子可以更改主服务器及其二进制日志坐标。当想要设置从属服务器来复制主服务器时使用ã€�
第二个例子显示了较少被使用的一个操作。当从属服务器含有中继日志,并且您出于某种原因想要执行此日志时使用。要这么做时,不需要连接主服务器。您只需要使ç”�CHANGE MASTER TO并启åŠ�SQL线程ï¼�START SLAVE SQL_THREAD)ã€�
您甚至可以在一个用于独立非从属服务器的非复制型设置中使用第二种操作,在崩溃之后进行复原。假设您的服务器已崩溃,同时您已恢复了备份。您想要重新播放服务器自己的二进制日志(不是中继日志,而是正规的二进制文件),例如名为myhost-bin.*。首先,应在安全的地方制作这些二进制日志的备份,以防您没有完全遵守以下步骤,意外地让服务器清理了二进制文件。使ç”�SET GLOBAL relay_log_purge=0,进一步增加安全性。然后启动不å��--log-bin选项的服务器。使ç”�--replicate-same-server-id, --relay-log=myhost-bin(让服务器相信,这些正规的二进制日志是中继日志)å’�--skip-slave-start options选项。当服务器启动后,发布以下语句:
mysql> CHANGE MASTER TO
-> RELAY_LOG_FILE='myhost-bin.153',
-> RELAY_LOG_POS=410,
-> MASTER_HOST='some_dummy_string';
mysql> START SLAVE SQL_THREAD;
服务器会读取并执行自己的二进制日志,完成崩溃复原。当复原完成后,运行STOP SLAVE,关闭服务器,删é™�master.infoå’�relay-log.info,并使用原来的选项重新启动服务器ã€�
要让服务器认为它是一个从属服务器,需要指å®�MASTER_HOST(甚至使用假值)ã€�
LOAD DATA FROM MASTER
本命令用于对主服务器进行快照,并拷贝到从属服务器上。它可以更新MASTER_LOG_FILEå’�MASTER_LOG_POS的值,这样,从属服务器就可以从正确的位置开始进行复制。使ç”�--replicate-*-do-*å’�--replicate-*-ignore-*选项指定的表和数据库排除规则均被兑现ã€�--replicate-rewrite-db没有被考虑。这是因为使用本选项,用户就可以设置一个例å¦�--replicate-rewrite-db=db1->db3å’�--replicate-rewrite-db=db2->db3的非唯一映射。当从主服务器载入表时,该映射会使从属服务器发生混淆ã€�
本语句的使用受以下条件的制约ï¼�
· 只对MyISAM表起作用。如果试图载入一个非MyISAM表,会导致以下错误:
· ERROR 1189 (08S01): Net error reading from master
· 当拍摄快照时,会获得对主服务器的全局读取锁定。在载入操作期间,该锁定会阻止对主服务器的更新ã€�
如果您正在载入大表,您可能必须对主服务器和从属服务器均增åŠ�net_read_timeoutå’�net_write_timeout值。请参见5.3.3节,“服务器系统变量â€�ã€�
注意ï¼�LOAD DATA FROM MASTER不从mysql数据库拷贝任何表。这可以更容易地让主服务器和从属服务器拥有不同的用户和权限ã€�
LOAD DATA FROM MASTER语句要求用于连接主服务器的复制帐户,以便让主服务器拥æœ�RELOADå’�SUPER权限,并让所有您想要载入的主服务器表拥有SELECT权限。所有的用户不拥æœ�SELECT权限的主服务器表均被LOAD DATA FROM MASTER忽略。这是因为主服务器会对用户隐藏它们:LOAD DATA FROM MASTER会调ç”�SHOW DATABASES以了解要载入的主服务器数据库,但æ˜�SHOW DATABASES只会返回用户有部分权限的数据库。请参见13.5.4.6节,“SHOW DATABASES语法â€�。在从属服务器方面,发布LOAD DATA FROM MASTER的用户应拥有授权,以取消或创建被复制的数据库和表ã€�
LOAD TABLE tbl_name FROM MASTER
用于把表的拷贝从主服务器转移到从属服务器。本语句的主要作用是调试LOAD DATA FROM MASTER。它要求用于连接主服务器的帐户拥有对主服务器çš�RELOADå’�SUPER权限,并拥有对要载入的主服务器表çš�SELECT权限。在从属服务器方面,发布LOAD TABLE FROM MASTER的用户应拥有取消和创建表的权限ã€�
用于LOAD DATA FROM MASTER的条件也适用于这里。举例说明,LOAD TABLE FROM MASTER仅对äº�MyISAM表起作用。对LOAD DATA FROM MASTER的暂停注意也适用ã€�
SELECT MASTER_POS_WAIT('master_log_file', master_log_pos)
这实际上是一个函数,而不是一个语句。它被用于确认,从属服务器已读取并执行了到达主服务器二进制日志的给定位置。要了解完整的描述,请参è§�12.9.4节,“其他函数â€�RESET SLAVE
用于让从属服务器忘记其在主服务器的二进制日志中的复制位置。本语句被用于进行一个明确的启动:它会删é™�master.infoå’�relay-log.info文件,以及所有的中继日志,并启动一个新的中继日志ã€�
注释:所有的中继日志被删除,即使它们没有被从属服务器SQL线程完全的执行。(如果您已经发布了一ä¸�SLAVE语句或如果从属服务器的载入量很大,则这对于一个复制从属服务器是一个很可能出现的情况。)
存储åœ�master.info文件中的连接信息通过使用在对应的启动选项中指定的值,被立即重新设置了。此信息包括主服务器主机、主服务器接口、主服务器用户和主服务器 密码等值。当从属服务å™�SQL线程被中止时,它位于正在复制的临时表的中间,并且发布äº�RESET SLAVE,则已被复制的临时表在从属服务器中被删除ã€�
SHOW SLAVE STATUS
用于提供有关从属服务器线程的关键参数的信息。如果您使用mysql客户端发布此语句,则您可以使用一ä¸�\G语句终止符来获得更便于阅读的竖向版面,而不是使用分号:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: localhost
Master_User: root
Master_Port: 3306
Connect_Retry: 3
Master_Log_File: gbichot-bin.005
Read_Master_Log_Pos: 79
Relay_Log_File: gbichot-relay-bin.005
Relay_Log_Pos: 548
Relay_Master_Log_File: gbichot-bin.005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 79
Relay_Log_Space: 552
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 8
SHOW SLAVE STATUS会返回以下字段:
· Slave_IO_State
SHOW PROCESSLIST输出çš�State字段的拷贝ã€�SHOW PROCESSLIST用于从属I/O线程。如果线程正在试图连接到主服务器,正在等待来自主服务器的时间或正在连接到主服务器等,本语句会通知您。在6.3节,“复制实施细节â€�中列出了可能的状态。旧版本çš�MySQL在连接主服务器不成功时,允许线程继续运行。对于旧版本çš�MySQL,观看此字段是必须的。如果它正在运行,则无问题;如果它没有运行,则您会在Last_Error字段中发现错误(后面有说明)ã€�
· Master_Host
当前的主服务器主机ã€�
· Master_User
被用于连接主服务器的当前用户ã€�
· Master_Port
当前的主服务器接口ã€�
· Connect_Retry
--master-connect-retry选项的当前å€�
· Master_Log_File
I/O线程当前正在读取的主服务器二进制日志文件的名称ã€�
· Read_Master_Log_Pos
在当前的主服务器二进制日志中ï¼�I/O线程已经读取的位置ã€�
· Relay_Log_File
SQL线程当前正在读取和执行的中继日志文件的名称ã€�
· Relay_Log_Pos
在当前的中继日志中,SQL线程已读取和执行的位置ã€�
· Relay_Master_Log_File
ç”�SQL线程执行的包含多数近期事件的主服务器二进制日志文件的名称ã€�
· Slave_IO_Running
I/O线程是否被启动并成功地连接到主服务器上。对于旧版本çš�MySQL(在4.1.14å’�5.0.12之前),如果I/O线程已被启动,即使从属服务器仍没有连接到主服务器上,Slave_IO_Running也将被设置到YESã€�
· Slave_SQL_Running
SQL线程是否被启动ã€�
· Replicate_Do_DB, Replicate_Ignore_DB
使用--replicate-do-dbå’�--replicate-ignore-db选项指定的数据库清单ã€�
· Replicate_Do_Table, Replicate_Ignore_Table, Replicate_Wild_Do_Table, Replicate_Wild_Ignore_Table
使用--replicate-do-table, --replicate-ignore-table, --replicate-wild-do-tableå’�--replicate-wild-ignore_table选项指定的表清单ã€�
· Last_Errno, Last_Error
被多数最近被执行的查询返回的错误数量和错误消息。错误数量为0并且消息为空字符串意味着“没有错误”。如æž�Last_Error值不是空值,它也会在从属服务器的错误日志中作为消息显示ã€�
举例说明ï¼�
Last_Errno: 1051
Last_Error: error 'Unknown table 'z'' on query 'drop table z'
该消息指示,è¡�z曾经存在于在主服务器中并已被取消了,但是它没有在从属服务器中存在过,因此对于从属服务器,DROP TABLE失败。(举例说明,在设置复制时,如果您忘记了把此表拷贝到从属服务器中,则这有可能发生。)
· Skip_Counter
最近被使用的用äº�SQL_SLAVE_SKIP_COUNTER的值ã€�
· Exec_Master_Log_Pos
来自主服务器的二进制日志的由SQL线程执行的上一个时间的位置ï¼�Relay_Master_Log_File)。在主服务器的二进制日志中的(Relay_Master_Log_File, Exec_Master_Log_Pos)对应于在中继日志中的(Relay_Log_File, Relay_Log_Pos)ã€�
· Relay_Log_Space
所有原有的中继日志结合起来的总大小ã€�
· Until_Condition, Until_Log_File, Until_Log_Pos
åœ�START SLAVE语句çš�UNTIL子句中指定的值ã€�
Until_Condition具有以下值:
o 如果没有指定UNTIL子句,则没有å€�
o 如果从属服务器正在读取,直到达到主服务器的二进制日志的给定位置为止,则值为Master
o 如果从属服务器正在读取,直到达到其中继日志的给定位置为止,则值为Relay
Until_Log_Fileå’�Until_Log_Pos用于指示日志文件名和位置值。日志文件名和位置值定义了SQL线程在哪个点中止执行ã€�
· Master_SSL_Allowed, Master_SSL_CA_File, Master_SSL_CA_Path, Master_SSL_Cert, Master_SSL_Cipher, Master_SSL_Key
这些字段显示了被从属服务器使用的参数。这些参数用于连接主服务器ã€�
Master_SSL_Allowed具有以下值:
o 如果允许对主服务器进è¡�SSL连接,则值为Yes
o 如果不允许对主服务器进行SSL连接,则值为No
o 如果允许SSL连接,但是从属服务器没有è®�SSL支持被启用,则值为Ignoredã€�
ä¸�SSL有关的字段的值对应于--master-ca, --master-capath, --master-cert, --master-cipherå’�--master-key选项的值ã€�
· Seconds_Behind_Master
本字段是从属服务器“落后”多少的一个指示。当从属SQL线程正在运行时(处理更新),本字段为在主服务器上由此线程执行的最近的一个事件的时间标记开始,已经过的秒数。当此线程被从属服务å™�I/O线程赶上,并进入闲置状态,等待来自I/O线程的更多的事件时,本字段为零。总之,本字段测量从属服务å™�SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计ã€�
如果主服务器和从属服务器之间的网络连接较快,则从属服务器I/O线程会非常接近主服务器,所以本字段能够十分近似地指示,从属服务å™�SQL线程比主服务器落后多少。如果网络较慢,则这种指示不准确;从å±�SQL线程经常会赶上读取速度较慢地从属服务器I/O线程,因此,Seconds_Behind_Master经常显示值为0。即ä½�I/O线程落后于主服务器时,也是如此。换句话说,本列只对速度快的网络有用ã€�
即使主服务器和从属服务器不具有相同的时钟,时间差计算也会起作用(当从属服务器I/O线程启动时,计算时间差。并假定从此时以后,时间差保持不变)。如果从å±�SQL线程不运行,或者如果从属服务器I/O线程不运行或未与主服务器连接,则Seconds_Behind_Masterä¸�NULL(意义为“未知”)。举例说明,如果在重新连接之前,从属服务å™�I/O线程休眠äº�master-connect-retry秒,则显ç¤�NULL,因为从属服务器不知道主服务器正在做什么,也不能有把握地说落后多少ã€�
本字段有一个限制。时间标记通过复制被保留,这意味着,如果一个主服务å™�M1本身是一个从属服务器M0,则来自M1çš�binlog的任何事件(通过复制来自M0çš�binlog的事件而产生),与原事件具有相同的时间标记。这可以ä½�MySQL成功地复åˆ�TIMESTAMP。但是,Seconds_Behind_Master的缺点是,如æž�M1也收到来自客户端的直接更新,则值会随机变化,因为有时最近的M1时间来自M0,有时来自直接更新,最近的时间标记也是如此ã€�
START SLAVE [thread_type [, thread_type] ... ]
START SLAVE [SQL_THREAD] UNTIL
MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
START SLAVE [SQL_THREAD] UNTIL
RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos
thread_type: IO_THREAD | SQL_THREAD
不含选项çš�START SLAVE会同时启动两个从属服务器线程ã€�I/O线程从主服务器中读取查询,并把它们存储在中继日志中ã€�SQL线程读取中继日志并执行查诀€�START SLAVE要求SUPER权限ã€�
如果START SLAVE成功地启动了从属服务器线程,则会返回,不会出现错误。但是,即使在此情况下,也有可能出现这样的现象——服务器线程启动了,然后又停止了(例如,因为它们没有成功地连接到主服务器上,或者没有能读取二进制日志,或者出现了其它问题)ã€�START SLAVE对此不会发出警告。您必须检查从属服务器的错误日志,查看是否有由从属服务器线程产生的错误消息,或者使ç”�SHOW SLAVE STATUS检查它们是否运行正常ã€�
您可以把IO_THREADå’�SQL_THREAD选项添加到语句中,指明哪些线程将要启动ã€�
可以添加一ä¸�UNTIL子句,指定从属服务器应启动并运行,直åˆ�SQL线程达到主服务器二进制日志中的一个给定点为止。当SQL线程达到此点时,它会停止。如果在该语句中指定äº�SQL_THREAD选项,则它只会启åŠ�SQL线程。否则,它会同时启动两个从属服务器线程。如æž�SQL线程正在运行,则UNTIL子句被忽略,并发布一个警告ã€�
对于一ä¸�UNTIL子句,您必须同时指定一个日志文件名和位置。不要把主服务器和中继日志选项混合在一起ã€�
UNTIL条件由一个后续的STOP SLAVE语句,或一个不包括UNTIL子句çš�START SLAVE语句,或一个服务器重启命令重新设置ã€�
UNTIL子句对于调试复制操作是有用的,或者可用于促使复制操作继续,直到接近一个特定的点时为止,在此点,您想要避免让从属服务器复制一个语句。举例说明,如果在主服务上执行了一个不明智çš�DROP TABLE语句,您可以使用UNTIL来告知从属服务器,执行到此点就停止,不要再继续了。要查找该事件是什么,需对主服务器日志或从属中继日志使用mysqlbinlog,或通过使用SHOW BINLOG EVENTS语句ã€�
如果您正在使ç”�UNTIL,让从属服务器成段地处理已复制的查询,则建议您使ç”�--skip-slave-start选项来启动从属服务器,以防止当从属服务器启动时,SQL线程运行。最好在一个选项文件中使用此选项,而不是在命令行中使用,这样,如果发生了意料外的服务器重新启动,它也不会被忘记ã€�
SHOW SLAVE STATUS语句包括了输出字段。这些字段显示了UNTIL条件的当前值ã€�
在以前版本的MySQL中,本语句被称为SLAVE START。在MySQL 5.1中仍然接受这种用法,以便与以前版本兼容。但现在不赞成使用ã€�
MySQL 5.1对服务器一方的预制语句提供支持。如果您使用合适的客户端编程界面,则这种支持可以发挥在MySQL 4.1中实施的高效客户ç«�/服务器二进制协议的优势。候选界面包æ‹�MySQL C API客户端库(用äº�C程序)ã€�MySQL Connector/J(用äº�Java程序)和MySQL Connector/NET。例如,C API可以提供一套能组成预制语句API的函数调用。请参见25.2.4节,“C API预处理语句â€�。其它语言界面可以对使用了二进制协议(通过åœ�C客户端库中链接)的预制语句提供支持。有一个例子是PHP 5.0中的mysqli扩展ã€�
对预制语句,还有一ä¸�SQL界面可以利用。与在整个预制语å��API中使用二进制协议相比,本界面效率没有那么高,但是它不要求编程,因为在SQL层级,可以直接利用本界面ï¼�
· 当您无法利用编程界面时,您可以使用本界面ã€�
· 有些程序允许您发é€�SQL语句到将被执行的服务器中,比å¦�mysql客户端程序。您可以从这些程序中使用本界靀€�
· 即使客户端正在使用旧版本的客户端库,您也可以使用本界靀€‚唯一的要求是,您能够连接到一个支持预制语å��SQL语法的服务器上ã€�
预制语句çš�SQL语法在以下情况下使用ï¼�
· 在编代码前,您想要测试预制语句在您的应用程序中运行得如何。或者也许一个应用程序在执行预制语句时有问题,您想要确定问题是什么ã€�
· 您想要创建一个测试案例,该案例描述了您使用预制语句时出现的问题,以便您编制程序错误报告ã€�
· 您需要使用预制语句,但是您无法使用支持预制语句的编程APIã€�
预制语句çš�SQL语法基于三个SQL语句ï¼�
PREPARE stmt_name FROM preparable_stmt;
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
{DEALLOCATE | DROP} PREPARE stmt_name;
PREPARE语句用于预备一个语句,并赋予它名称stmt_name,借此在以后引用该语句。语句名称对案例不敏感ã€�preparable_stmt可以是一个文字字符串,也可以是一个包含了语句文本的用户变量。该文本必须展现一个单一çš�SQL语句,而不是多个语句。使用本语句,â€�?’字符可以被用于制作参数,以指示当您执行查询时,数据值在哪里与查询结合在一起。â€�?’字符不应加引号,即使您想要把它们与字符串值结合在一起,也不要加引号。参数制作符只能被用于数据值应该出现的地方,不用于SQL关键词和标识符等ã€�
如果带有此名称的预制语句已经存在,则在新的语言被预备以前,它会被隐含地解除分配。这意味着,如果新语句包含一个错误并且不能被预备,则会返回一个错误,并且不存在带有给定名称语句ã€�
预制语句的范围是客户端会话。在此会话内,语句被创建。其它客户端看不到它ã€�
在预备了一个语句后,您可使用一ä¸�EXECUTE语句(该语句引用了预制语句名称)来执行它。如果预制语句包含任何参数制造符,则您必须提供一个列举了用户变量(其中包含要与参数结合的值)çš�USING子句。参数值只能有用户变量提供ï¼�USING子句必须准确地指明用户变量。用户变量的数目与语句中的参数制造符的数量一样多ã€�
您可以多次执行一个给定的预制语句,在每次执行前,把不同的变量传递给它,或把变量设置为不同的值ã€�
要对一个预制语句解除分配,需使用DEALLOCATE PREPARE语句。尝试在解除分配后执行一个预制语句会导致错误ã€�
如果您终止了一个客户端会话,同时没有对以前已预制的语句解除分配,则服务器会自动解除分配ã€�
以下SQL语句可以被用在预制语句中ï¼�CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE和多数的SHOW语句。目前不支持其它语句ã€�
以下例子显示了预备一个语句的两种方法。该语句用于在给定了两个边的长度时,计算三角形的斜边ã€�
第一个例子显示如何通过使用文字字符串来创建一个预制语句,以提供语句的文本ï¼�
mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;
第二个例子是相似的,不同的是提供了语句的文本,作为一个用户变量:
mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;
预制语句çš�SQL语法不能被用于带嵌套的风格中。也就是说,被传递给PREPARE的语句本身不能是一ä¸�PREPARE, EXECUTEæˆ�DEALLOCATE PREPARE语句ã€�
预制语句çš�SQL语法与使用预制语å��API调用不同。例如,您不能使ç”�mysql_stmt_prepare() C API函数来预备一ä¸�PREPARE, EXECUTEæˆ�DEALLOCATE PREPARE语句ã€�
预制语句çš�SQL语法可以在已存储的过程中使用,但是不能在已存储的函数或触发程序中使用ã€�
当使用预制语句时,可以在LIMIT子句中使用占位符。请参见13.2.7节,“SELECT语法â€�ã€�
这是MySQL参考手册的翻译版本,关于MySQL参考手册,请访é—�dev.mysql.comã€� 原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的ã€�