mysql5.5手册读书日记(3)

<?php

/*
MySQL_5.5中文参考手册 587开始 与GROUP BY子句同时使用的函数和修改程序
12.10.1. GROUP BY(聚合)函数
12.10.2. GROUP BY修改程序
12.10.3. 具有隐含字段的GROUP BY
12.10.1. GROUP BY(聚合)函数
本章论述了用于一组数值操作的 group (集合)函数。除非另作说明, group 函数会忽略 NULL 值。
假如你在一个不包含 ROUP BY子句的语句中使用一个 group函数,它相当于对所有行进行分组。
AVG([DISTINCT] expr)
返回expr 的平均值。 DISTINCT 选项可用于返回expr的不同值的平均值。
若找不到匹配的行,则AVG()返回 NULL 。
mysql> SELECT student_name, AVG(test_score)
-> FROM student
-> GROUP BY student_name;
BIT_AND(expr)
返回expr中所有比特的 bitwise AND 。计算执行的精确度为64比特(BIGINT) 。
若找不到匹配的行,则这个函数返回 18446744073709551615 。(这是无符号 BIGINT 值,所有比特被设置为
1)。
BIT_OR(expr)
返回expr 中所有比特的bitwise OR。计算执行的精确度为64比特(BIGINT) 。
若找不到匹配的行,则函数返回 0 。
BIT_XOR(expr)
返回expr 中所有比特的bitwise XOR。计算执行的精确度为64比特(BIGINT) 。 若找不到匹配的行,则函数返回 0 。
COUNT(expr)
返回SELECT语句检索到的行中非NULL值的数目。
若找不到匹配的行,则COUNT() 返回 0 。
mysql> SELECT student.student_name,COUNT(*)
-> FROM student,course
-> WHERE student.student_id=course.student_id
-> GROUP BY student_name;
COUNT(*) 的稍微不同之处在于,它返回检索行的数目, 不论其是否包含 NULL值。
SELECT 从一个表中检索,而不检索其它的列,并且没有 WHERE子句时, COUNT(*)被优化到最快的返回速
度。例如:
mysql> SELECT COUNT(*) FROM student;
这个优化仅适用于 MyISAM表, 原因是这些表类型会储存一个函数返回记录的精确数量,而且非常容易访
问。对于事务型的存储引擎(InnoDB, BDB), 存储一个精确行数的问题比较多,原因是可能会发生多重事物处
理, 而每个都可能会对行数产生影响。
COUNT(DISTINCT expr,[expr...])
返回不同的非NULL值数目。
若找不到匹配的项,则COUNT(DISTINCT)返回 0 。
mysql> SELECT COUNT(DISTINCT results) FROM student;
在MySQL中, 你通过给定一个表达式列表而获取不包含NULL 不同表达式组合的数目。在标准 SQL中,你将必须
在COUNT(DISTINCT ...)中连接所有表达式。
GROUP_CONCAT(expr)
该函数返回带有来自一个组的连接的非NULL值的字符串结果。其完整的语法如下所示:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val])
mysql> SELECT student_name,
-> GROUP_CONCAT(test_score)
-> FROM student -> GROUP BY student_name;
Or:
mysql> SELECT student_name,
-> GROUP_CONCAT(DISTINCT test_score
-> ORDER BY test_score DESC SEPARATOR ' ')
-> FROM student
-> GROUP BY student_name;
在MySQL中,你可以获取表达式组合的连接值。你可以使用DISTINCT删去重复值。假若你希望多结果值进行排
序,则应该使用 ORDER BY子句。若要按相反顺序排列,将 DESC (递减) 关键词添加到你要用ORDER BY 子
句进行排序的列名称中。默认顺序为升序;可使用ASC将其明确指定。 SEPARATOR 后面跟随应该被插入结
果的值中间的字符串值。默认为逗号 (‘,’)。通过指定SEPARATOR '' ,你可以删除所有分隔符。
使用group_concat_max_len系统变量,你可以设置允许的最大长度。程序中进行这项操作的语法如下,其中
val 是一个无符号整数:
SET [SESSION | GLOBAL] group_concat_max_len = val;
若已经设置了最大长度, 则结果被截至这个最大长度。
MIN([DISTINCT] expr), MAX([DISTINCT] expr)
返回expr 的最小值和最大值。 MIN() 和 MAX() 的取值可以是一个字符串参数;在这些情况下, 它们返回最小
或最大字符串值。请参见7.4.5节,“MySQL如何使用索引”。 DISTINCT关键词可以被用来查找expr 的不同值
的最小或最大值,然而,这产生的结果与省略DISTINCT 的结果相同。
若找不到匹配的行,MIN()和MAX()返回 NULL 。
mysql> SELECT student_name, MIN(test_score), MAX(test_score)
-> FROM student
-> GROUP BY student_name;
对于MIN()、 MAX()和其它集合函数, MySQL当前按照它们的字符串值而非字符串在集合中的相关位置比较
ENUM和 SET 列。这同ORDER BY比较二者的方式有所不同。这一点应该在MySQL的未来版本中得到改善。
STD(expr) STDDEV(expr)
返回expr 的总体标准偏差。这是标准 SQL 的延伸。这个函数的STDDEV() 形式用来提供和Oracle 的兼容性。
可使用标准SQL函数 STDDEV_POP() 进行代替。
若找不到匹配的行,则这些函数返回 NULL 。
STDDEV_POP(expr)
返回expr 的总体标准偏差(VAR_POP()的平方根)。你也可以使用 STD() 或STDDEV(), 它们具有相同的意义,
然而不是标准的 SQL。
若找不到匹配的行,则STDDEV_POP()返回 NULL。 STDDEV_SAMP(expr)
返回expr 的样本标准差 ( VAR_SAMP()的平方根)。
若找不到匹配的行,则STDDEV_SAMP() 返回 NULL 。
SUM([DISTINCT] expr)
返回expr 的总数。 若返回集合中无任何行,则 SUM() 返回NULL。DISTINCT 关键词可用于 MySQL 5.1 中,
求得expr 不同值的总和。
若找不到匹配的行,则SUM()返回 NULL。
VAR_POP(expr)
返回expr 总体标准方差。它将行视为总体,而不是一个样本, 所以它将行数作为分母。你也可以使用
VARIANCE(),它具有相同的意义然而不是标准的 SQL。
若找不到匹配的项,则VAR_POP()返回NULL。
VAR_SAMP(expr)
返回expr 的样本方差。更确切的说,分母的数字是行数减去1。
若找不到匹配的行,则VAR_SAMP()返回NULL。
VARIANCE(expr)
返回expr 的总体标准方差。这是标准SQL 的延伸。可使用标准SQL 函数 VAR_POP() 进行代替。
若找不到匹配的项,则VARIANCE()返回NULL。
12.10.2. GROUP BY修改程序
GROUP BY子句允许一个将额外行添加到简略输出端 WITH ROLLUP 修饰符。这些行代表高层(或高聚集)简略
操作。ROLLUP 因而允许你在多层分析的角度回答有关问询的问题。例如,它可以用来向OLAP (联机分析处
理) 操作提供支持。
设想一个名为sales 的表具有年份、国家、产品及记录销售利润的利润列:
CREATE TABLE sales
(
year INT NOT NULL,
country VARCHAR(20) NOT NULL,
product VARCHAR(32) NOT NULL,
profit INT
);
可以使用这样的简单GROUP BY,每年对表的内容做一次总结: mysql> SELECT year, SUM(profit) FROM sales GROUP BY year;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
+------+-------------+
这个输出结果显示了每年的总利润, 但如果你也想确定所有年份的总利润,你必须自己累加每年的单个值或运
行一个加法询问。
或者你可以使用 ROLLUP, 它能用一个问询提供双层分析。将一个 WITH ROLLUP修饰符添加到GROUP BY 语
句,使询问产生另一行结果,该行显示了所有年份的总价值:
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
| NULL | 7535 |
+------+-------------+
总计高聚集行被年份列中的NULL值标出。
当有多重 GROUP BY 列时,ROLLUP产生的效果更加复杂。这时,每次在除了最后一个分类列之外的任何列出
现一个 “break” (值的改变) ,则问讯会产生一个高聚集累计行。
例如,在没有 ROLLUP的情况下,一个以年、国家和产品为基础的关于 sales 表的一览表可能如下所示:
mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product;
+------+---------+------------+-------------+
| year | country | product | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 | | 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2001 | Finland | Phone | 10 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
+------+---------+------------+-------------+
表示总值的输出结果仅位于年/国家/产品的分析级别。当添加了 ROLLUP后, 问询会产生一些额外的行:
mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+
| year | country | product | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | India | NULL | 1350 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2000 | USA | NULL | 1575 |
| 2000 | NULL | NULL | 4525 |
| 2001 | Finland | Phone | 10 |
| 2001 | Finland | NULL | 10 |
| 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
| 2001 | USA | NULL | 3000 |
| 2001 | NULL | NULL | 3010 |
| NULL | NULL | NULL | 7535 |
+------+---------+------------+-------------+
对于这个问询, 添加ROLLUP 子句使村输出结果包含了四层分析的简略信息,而不只是一个下面是怎样解释
ROLLUP输出:
一组给定的年份和国家的每组产品行后面, 会产生一个额外的总计行, 显示所有产品的总值。这些行将
产品列设置为 NULL。
一组给定年份的行后面,会产生一个额外的总计行,显示所有国家和产品的总值。这些行将国家和产品
列设置为 NULL。
最后, 在所有其它行后面,会产生一个额外的总计列,显示所有年份、国家及产品的总值。这一行将年
份、国家和产品列设置为 NULL。
使用ROLLUP 时的其它注意事项
以下各项列出了一些MySQL执行ROLLUP的特殊状态:
当你使用 ROLLUP时, 你不能同时使用 ORDER BY子句进行结果排序。换言之, ROLLUP 和ORDER BY 是互相
排斥的。然而,你仍可以对排序进行一些控制。在 MySQL中, GROUP BY 可以对结果进行排序,而且你可以
在GROUP BY列表指定的列中使用明确的 ASC和DESC关键词,从而对个别列进行排序。 (不论如何排序
被ROLLUP添加的较高级别的总计行仍出现在它们被计算出的行后面)。
LIMIT可用来限制返回客户端的行数。LIMIT 用在 ROLLUP后面, 因此这个限制会取消被ROLLUP添加的行。例
如:
mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product WITH ROLLUP
-> LIMIT 5;
+------+---------+------------+-------------+
| year | country | product | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
+------+---------+------------+-------------+
将ROLLUP同 LIMIT一起使用可能会产生更加难以解释的结果,原因是对于理解高聚集行,你所掌握的上下文
较少。
在每个高聚集行中的NULL 指示符会在该行被送至客户端时产生。服务器会查看最左边的改变值后面的GROUP
BY子句指定的列。对于任何结果集合中的,有一个词匹配这些名字的列, 其值被设为 NULL。(若你使用列数字
指定了分组列,则服务器会通过数字确定将哪个列设置为 NULL)。
由于在高聚集行中的 NULL值在问询处理阶段被放入结果集合中,你无法将它们在问询本身中作为NULL值检
验。例如,你无法将 HAVING product IS NULL 添加到问询中,从而在输出结果中删去除了高聚集行以外的部
分。
另一方面, NULL值在客户端不以 NULL 的形式出现, 因而可以使用任何MySQL客户端编程接口进行检验。
12.10.3. 具有隐含字段的GROUP BY
MySQL 扩展了 GROUP BY的用途,因此你可以使用SELECT 列表中不出现在GROUP BY语句中的列或运算。这
代表 “对该组的任何可能值 ”。你可以通过避免排序和对不必要项分组的办法得到它更好的性能。例如,在下
列问询中,你无须对customer.name 进行分组:
mysql> SELECT order.custid, customer.name, MAX(payments)
-> FROM order,customer
-> WHERE order.custid = customer.custid
-> GROUP BY order.custid;
在标准SQL中, 你必须将 customer.name添加到 GROUP BY子句中。在MySQL中, 假如你不在ANSI模式中运
行,则这个名字就是多余的。
假如你从 GROUP BY 部分省略的列在该组中不是唯一的,那么不要使用这个功能! 你会得到非预测性结果。
在有些情况下,你可以使用MIN()和MAX() 获取一个特殊的列值,即使他不是唯一的。下面给出了来自包含排序
列中最小值的列中的值:
SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)
See 3.6.4节,“拥有某个字段的组间最大值的行”.
注意,假如你正在尝试遵循标准 SQL, 你不能使用GROUP BY或 ORDER BY子句中的表达式。你可以通过使用
表达式的别名绕过这一限制:
mysql> SELECT id,FLOOR(value/100) AS val
-> FROM tbl_name
-> GROUP BY id, val ORDER BY val;
然而, MySQL允许你使用GROUP BY 及 ORDER BY 子句中的表达式。例如:
mysql> SELECT id, FLOOR(value/100) FROM tbl_name ORDER BY RAND(); 如果您想要更改列的类型而不是名称, 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时)有多少记录
由于重复关键字的原因已被删除 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命令的详细信息 多个附加子句用于提供分区维护和修补功能。这些功能与用于非分区表的功能类似。这些功能由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开始。 在创建表格时,您可以使用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 索引文件 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 见15.4节,“MEMORY (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 成簇表,容错表,以存储器为基础的表。也称为NDB。请参见第17章:MySQL簇。
要了解有关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过程中进
行联合插入 给表重命名 RENAME TABLE current_db.tbl_name TO other_db.tbl_name; 如果您编写的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忽略所有的错误。(在分析阶段遇到的错误会以常规方
式处理。)由于使用本选项而被忽略的错误会作为警告返回。 删除操作的速度会受到一些因素的影响
在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 ...
目前,您不能从一个表中删除,同时又在子查询中从同一个表中选择。 DO语法
DO expr [, expr] ...
DO用于执行表达式,但是不返回任何结果。DO是SELECT expr的简化表达方式。DO有一个优势,就是如果您
不太关心结果的话,DO的速度稍快。
DO主要用于执行有副作用的函数,比如RELEASE_LOCK()。 HANDLER语法
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 ... SELECT语法 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 ...
用于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 REPLACE语法
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. 再次尝试把新行插入到表中 在没有表被引用的情况下,允许您指定DUAL作为一个假的表名。
· mysql> SELECT 1 + 1 FROM DUAL;
· -> 2
有些服务器要求一个FROM子句。DUAL仅用于与这些服务器兼容。如果没有表被引用,则MySQL不要求该子
句,前面的语句可以按以下方法编写:
mysql> SELECT 1 + 1;
-> 2 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中,本语句不运行。) MySQL prepare语法:
PREPARE statement_name FROM preparable_SQL_statement; /*定义*/
EXECUTE statement_name [USING @var_name [, @var_name] ...]; /*执行预处理语句*/
{DEALLOCATE | DROP} PREPARE statement_name /*删除定义*/ ; PREPARE语句用于预备一个语句,并指定名称statement_name,以后引用该语句。语句名称对大小写不敏感。preparable_stmt可以是一个文字字符串,
也可以是一个包含了语句文本的用户变量。
该文本必须表现为一个单一的SQL语句,而不是多个语句。在这语句里,‘?'字符可以被用于标识参数,当执行时,以指示数据值绑定到查询后。‘?'字符不应加引号,
即使你想要把它们与字符串值结合在一起。
参数标记只能用于数据值应该出现的地方,而不是SQL关键字,标识符,等等。
如果预语句已经存在,则在新的预语句被定义前,它会被隐含地删掉。 每次都看别人的,今天我自己写下来,以后就不用看别人的了
语法
PREPARE statement_name FROM sql_text /*定义*/
EXECUTE statement_name [USING variable [,variable...]] /*执行预处理语句*/
DEALLOCATE PREPARE statement_name /*删除定义*/ 为了与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关键词的后面,您可以使用许多选项。这些选项可以影响语句的运行。
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 JOIN语法
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。该列将会从结果中被忽略 UNION语法
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。) 使用ANY, IN和SOME进行子查询
语法:
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有助于确认每个人都理解该查询的真正含义。
13.2.8.4. 使用ALL进行子查询
语法:
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); EXISTS和NOT EXISTS
如果一个子查询返回任何的行,则EXISTS subquery为FALSE。例如:
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?” TRUNCATE语法
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扩展 MySQL实用工具语句
13.3.1. DESCRIBE语法(获取有关列的信息)
13.3.2. USE语法
13.3.1. DESCRIBE语法(获取有关列的信息)
{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语
法”。
13.3.2. USE语法
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事务处理和锁定语句
13.4.1. START TRANSACTION, COMMIT和ROLLBACK语法
13.4.2. 不能回滚的语句
13.4.3. 会造成隐式提交的语句
13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT语法
13.4.5. LOCK TABLES和UNLOCK TABLES语法
13.4.6. SET TRANSACTION语法
13.4.7. XA事务
MySQL通过SET AUTOCOMMIT, START TRANSACTION, COMMIT和ROLLBACK等语句支持本地事务(在给定的
客户端连接中)。请参见13.4.1节,“START TRANSACTION, COMMIT和ROLLBACK语法”。XA事务支持还可以
允许MySQL参与分布式事务。请参见13.4.7节,“XA事务”。
13.4.1. START TRANSACTION, COMMIT和ROLLBACK语法
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,用于连接。
13.4.2. 不能回滚的语句
有些语句不能被回滚。通常,这些语句包括数据定义语言(DDL)语句,比如创建或取消数据库的语句,和创
建、取消或更改表或存储的子程序的语句。 您在设计事务时,不应包含这类语句。如果您在事务的前部中发布了一个不能被回滚的语句,则后部的其它语
句会发生错误,在这些情况下,通过发布ROLLBACK语句不能回滚事务的全部效果。
13.4.3. 会造成隐式提交的语句
以下语句(以及同义词)均隐含地结束一个事务,似乎是在执行本语句前,您已经进行了一个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被执行,用于任何当前事务。
13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT语法
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,则当前事务的所有保存点被删除。
13.4.5. LOCK TABLES和UNLOCK TABLES语法
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有关
的问题”。
13.4.6. SET TRANSACTION语法
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命令行选项”。
13.4.7. XA事务
13.4.7.1. XA事务SQL语法
13.4.7.2. XA事务状态
对于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)。例如,当一个事务管理器发现,一个全局事务
只由一个事务资源组成(即,单一分支),则该资源可以被告知同时进行预备和提交。
13.4.7.1. XA事务SQL语法
要在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部分的串联
13.4.7.2. XA事务状态
XA事务在以下状态下进展:
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语句不能被使用,直到该事务被提交或被回滚为 mysql> show variables like '%XA%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| innodb_support_xa | ON |
| min_examined_row_limit | 0 |
+------------------------+-------+ 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=tonu@example.com';
注意,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=tonu@example.com';
注意,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=tonu@example.com'
-> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
-> 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语法
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登录项。 表维护语句
13.5.2.1. ANALYZE TABLE语法
13.5.2.2. BACKUP TABLE语法
13.5.2.3. CHECK TABLE语法
13.5.2.4. CHECKSUM TABLE语法
13.5.2.5. OPTIMIZE TABLE语法
13.5.2.6. REPAIR TABLE语法
13.5.2.7. RESTORE TABLE语法
13.5.2.1. ANALYZE TABLE语法
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)。
13.5.2.2. BACKUP TABLE语法
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 消息
13.5.2.3. CHECK TABLE语法
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以外的值。
13.5.2.4. CHECKSUM TABLE语法
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。对于这种情况,会生成一个警告。
13.5.2.5. OPTIMIZE TABLE语法
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命令的作用相当于一个复制主服务
器,在默认情况下,这些命令将被复制到复制从属服务器中。
13.5.2.6. REPAIR 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语句。(通过制作一个备份来启动是一个好办法。)再最不利情况下,您可
以有一个新的干净的索引文件,不含有关数据文件的信息。然后,您执行的下一个操作会覆盖数据文件。这很
少发生,但是是有可能的。 13.5.2.7. RESTORE 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 消息 SHOW语法
13.5.4.1. SHOW CHARACTER SET语法
13.5.4.2. SHOW COLLATION语法
13.5.4.3. SHOW COLUMNS语法
13.5.4.4. SHOW CREATE DATABASE语法
13.5.4.5. SHOW CREATE TABLE语法
13.5.4.6. SHOW DATABASES语法
13.5.4.7. SHOW ENGINE语法
13.5.4.8. SHOW ENGINES语法
13.5.4.9. SHOW ERRORS语法
13.5.4.10. SHOW GRANTS语法
13.5.4.11. SHOW INDEX语法
13.5.4.12. SHOW INNODB STATUS语法
13.5.4.13. SHOW LOGS语法
13.5.4.14. SHOW OPEN TABLES语法
13.5.4.15. SHOW PRIVILEGES语法
13.5.4.16. SHOW PROCESSLIST语法
13.5.4.17. SHOW STATUS语法
13.5.4.18. SHOW TABLE STATUS语法
13.5.4.19. SHOW TABLES语法
13.5.4.20. SHOW TRIGGERS语法
13.5.4.21. SHOW VARIABLES语法
13.5.4.22. SHOW WARNINGS语法
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 ‘%’和‘_’通配
符的字符串。对于把语句输出值限定为匹配值,本样式是有用的。
13.5.4.1. SHOW CHARACTER SET语法
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列显示用于存储一个字符的最大的字节数目。
13.5.4.2. SHOW COLLATION语法
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与
对字符串(在字符集中表达)分类所需的存储器的数量有关。
13.5.4.3. SHOW COLUMNS语法
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语法(获取关于列的信
息)”。
13.5.4.4. SHOW CREATE DATABASE语法
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 */
13.5.4.5. SHOW CREATE TABLE语法
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语法”。
13.5.4.6. SHOW DATABASES语法
SHOW {DATABASES | SCHEMAS} [LIKE 'pattern']
SHOW DATABASES可以在MySQL服务器主机上列举数据库。您也可以使用mysqlshow命令得到此清单。您只
能看到您拥有某些权限的数据库,除非您拥有全局SHOW DATABASES权限。
如果服务器以--skip-show-database选项为起始,则您根本不能使用本语句,除非您拥有SHOW DATABASES权
限。
也可以使用SHOW SCHEMAS。
13.5.4.7. SHOW ENGINE语法
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起使用。
13.5.4.8. SHOW ENGINES语法
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-tabletype=
InnoDB选项为起始,则InnoDB行的Support值为DEFAULT值。请参见第15章:存储引擎和表类型。
13.5.4.9. SHOW ERRORS语法
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语法”。
13.5.4.10. SHOW GRANTS语法
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();
13.5.4.11. SHOW INDEX语法
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命令列举一个表的
索引。
13.5.4.12. SHOW INNODB STATUS语法
SHOW INNODB STATUS
在MySQL 5.1中,这是SHOW ENGINE INNODB STATUS的同义词,但不赞成使用。请参见13.5.4.7节,“SHOW
ENGINE语法”。
13.5.4.13. SHOW LOGS语法
SHOW [BDB] LOGS
在MySQL 5.1中,这是SHOW ENGINE BDB LOGS的同义词,但是不赞成使用。请参见13.5.4.7节,“SHOW
ENGINE语法”。
13.5.4.14. SHOW OPEN TABLES语法
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
表名称是否被锁定。名称锁定用于取消表或对表进行重命名等操作。
13.5.4.15. SHOW PRIVILEGES语法
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
13.5.4.16. SHOW PROCESSLIST语法
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管理程序已经处理了所有处于等待状态的插入,并正在等待新插入。
多数状态对应于非常快的操作。如果一个线程在这些状态下停留了数秒,则可能是有问题,需要进行调查。
有一些其它的状态,在前面的清单中没有提及,但是其中有很多状态对于查找服务器中的程序错误是有用的。
13.5.4.17. SHOW STATUS语法
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会得到同样的值。
13.5.4.18. SHOW TABLE STATUS语法
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称为视图。
13.5.4.19. SHOW TABLES语法
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输出中显
示。
13.5.4.20. SHOW TRIGGERS语法
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权限。
同时也见23.1.16节,“INFORMATION_SCHEMA TRIGGERS表”。
13.5.4.21. SHOW VARIABLES语法
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 |
+-----------------------+----------+
13.5.4.22. SHOW WARNINGS语法
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,使“注意”级别的警告不被记录。
13.5.5. 其它管理语句
13.5.5.1. CACHE INDEX语法
13.5.5.2. FLUSH语法
13.5.5.3. KILL语法
13.5.5.4. LOAD INDEX INTO CACHE语法
13.5.5.5. RESET语法
13.5.5.1. CACHE INDEX语法
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'
默认情况下,表索引被分配给在服务器启动时被创建的主(默认)键缓存。当一个键高速缓冲被破坏时,所有
被分配到此缓存中的索引会再次被分配给默认的键高速缓冲。
索引的分配会对服务器产生全局性影响:如果一个客户端把一个索引分配给一个给定的缓存,则不论什么客户
端发布查询,本缓存都被用于所有涉及索引的查询。
13.5.5.2. FLUSH语法
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语法”。
13.5.5.3. KILL语法
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操作会导致出现一个被损坏的没有用的
表。对这样的表的任何读取或写入都会失败,直到您再次优化或修复它(不中断)。
13.5.5.4. LOAD INDEX INTO CACHE语法
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语法允许您指定,只有来自表的特定的索引应被预载入。但是,当前实施会把所有
的表索引预载入缓存中,所以一定要指定表名称,不能指定其它的。
13.5.5.5. RESET语法 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语句” 复制语句
13.6.1. 用于控制主服务器的SQL语句
13.6.2. 用于控制从服务器的SQL语句
本节叙述了与复制有关的SQL语句。一组语句被用于控制主服务器。其它的被用于控制从属服务器。
13.6.1. 用于控制主服务器的SQL语句
13.6.1.1. PURGE MASTER LOGS语法
13.6.1.2. RESET MASTER语法
13.6.1.3. SET SQL_LOG_BIN语法
13.6.1.4. SHOW BINLOG EVENTS语法
13.6.1.5. SHOW MASTER LOGS语法
13.6.1.6. SHOW MASTER STATUS语法
13.6.1.7. SHOW SLAVE HOSTS语法
可以通过SQL界面控制复制。本节讨论了用于管理主复制服务器的语句。13.6.2节,“用于控制从服务器
的SQL语句”讨论了用于管理从属服务器的语句。
13.6.1.1. PURGE MASTER LOGS语法
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. 清理所有的日志,但是不包括目标日志。
13.6.1.2. RESET MASTER语法
RESET MASTER
可以删除列于索引文件中的所有二进制日志,把二进制日志索引文件重新设置为空,并创建一个新的二进制日
志文件。
13.6.1.3. SET SQL_LOG_BIN语法
SET SQL_LOG_BIN = {0|1}
如果客户端使用一个有SUPER权限的账户连接,则可以禁用或启用当前连接的二进制日志记录。如果客户端没
有此权限,则语句被拒绝,并伴随有错误。
13.6.1.4. SHOW BINLOG EVENTS语法
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:用于处理二进制日志文件的实用工具”。 13.6.1.5. SHOW MASTER LOGS语法
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相当。
13.6.1.6. SHOW MASTER STATUS语法
SHOW MASTER STATUS
用于提供主服务器二进制日志文件的状态信息。例如:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
13.6.1.7. SHOW SLAVE HOSTS语法
SHOW SLAVE HOSTS
用于显示当前使用主服务器注册的复制从属服务器的清单。不以--report-host=slave_name选项为开头的从属
服务器不会显示在本清单中。
13.6.2. 用于控制从服务器的SQL语句
13.6.2.1. CHANGE MASTER TO语法
13.6.2.2. LOAD DATA FROM MASTER语法
13.6.2.3. LOAD TABLE tbl_name FROM MASTER语法
13.6.2.4. MASTER_POS_WAIT()语法
13.6.2.5. RESET SLAVE语法
13.6.2.6. SET GLOBAL SQL_SLAVE_SKIP_COUNTER语法
13.6.2.7. SHOW SLAVE STATUS语法
13.6.2.8. START SLAVE语法 13.6.2.9. STOP SLAVE语法
复制操作可以通过SQL界面控制。本节讨论了用于管理从属复制服务器的语句。13.6.1节,“用于控制主服务器
的SQL语句”讨论了用于管理主服务器的语句。
13.6.2.1. CHANGE MASTER TO语法
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(甚至使用假值)。
13.6.2.2. LOAD DATA FROM MASTER语法
LOAD DATA FROM MASTER
本命令用于对主服务器进行快照,并拷贝到从属服务器上。它可以更
新MASTER_LOG_FILE和MASTER_LOG_POS的值,这样,从属服务器就可以从正确的位置开始进行复制。使
用--replicate-*-do-*和--replicate-*-ignore-*选项指定的表和数据库排除规则均被兑现。--replicate-rewritedb
没有被考虑。这是因为使用本选项,用户就可以设置一个例如--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的用户应拥有授权,以取消或创建被复制的数据库和表。
13.6.2.3. LOAD TABLE tbl_name 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的暂停注意也适用。
13.6.2.4. MASTER_POS_WAIT()语法
SELECT MASTER_POS_WAIT('master_log_file', master_log_pos)
这实际上是一个函数,而不是一个语句。它被用于确认,从属服务器已读取并执行了到达主服务器二进制日志
的给定位置。要了解完整的描述,请参见12.9.4节,“其他函数”
13.6.2.5. RESET SLAVE语法
RESET SLAVE
用于让从属服务器忘记其在主服务器的二进制日志中的复制位置。本语句被用于进行一个明确的启动:它会删
除master.info和relay-log.info文件,以及所有的中继日志,并启动一个新的中继日志。
注释:所有的中继日志被删除,即使它们没有被从属服务器SQL线程完全的执行。(如果您已经发布了一
个SLAVE语句或如果从属服务器的载入量很大,则这对于一个复制从属服务器是一个很可能出现的情况。)
存储在master.info文件中的连接信息通过使用在对应的启动选项中指定的值,被立即重新设置了。此信息包括
主服务器主机、主服务器接口、主服务器用户和主服务器密码等值。当从属服务器SQL线程被中止时,它位于
正在复制的临时表的中间,并且发布了RESET SLAVE,则已被复制的临时表在从属服务器中被删除。
13.6.2.6. SET GLOBAL SQL_SLAVE_SKIP_COUNTER语法
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n
从主服务器中跳过后面的n个事件。要复原由语句导致的复制中止,这是有用的。
仅当从属线程没有正在运行时,本语句时有效的。否则,会产生一个错误。
13.6.2.7. SHOW SLAVE STATUS语法
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,有时来自直接更新,最近的时间标记也是如
此。
13.6.2.8. START SLAVE语法
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中仍然接受这种用法,以便与以前版本兼
容。但现在不赞成使用。
13.6.2.9. STOP SLAVE语法
STOP SLAVE [thread_type [, thread_type] ... ]
thread_type: IO_THREAD | SQL_THREAD
用于中止从属服务器线程。STOP SLAVE要求SUPER权限。
和START SLAVE相似,本语句在使用时可以加IO_THREAD和SQL_THREAD选项,指明将被中止的线程。
在以前版本的MySQL中,本语句被称为SLAVE STOP。在MySQL 5.1中仍然接受这种用法,以便与以前版本兼
容。但是现在不赞成使用 用于预处理语句的SQL语法
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] ...];
Chapter 13. SQL Statement Syntax
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/sql-syntax.html[2010/2/24 5:22:43]
{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语法”。 */
?>
上一篇:CLR via C#读书日记一' 引用类型和值类型'


下一篇:[iOS]C语言技术视频-03-程序分支结构(switch)