mysql 数据操纵:SELECT, INSERT, UPDATE, DELETE

6.4 数据操纵:SELECT, INSERT, UPDATE, DELETE

6.4.1 SELECT 句法

SELECT [STRAIGHT_JOIN]
       [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
       [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY]
       [DISTINCT | DISTINCTROW | ALL]
    select_expression,...
    [INTO {OUTFILE | DUMPFILE} 'file_name' export_options]
    [FROM table_references
      [WHERE where_definition]
      [GROUP BY {unsigned_integer | col_name | formula} [ASC | DESC], ...]
      [HAVING where_definition]
      [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] ,...]
      [LIMIT [offset,] rows | rows OFFSET offset]
      [PROCEDURE procedure_name(argument_list)]
      [FOR UPDATE | LOCK IN SHARE MODE]]

SELECT 用于检索从一个或多个表中选取出的行。select_expression 表示你希望检索的列。 SELECT 也可以被用于检索没有引用任何表的计算列。例如:

mysql> SELECT 1 + 1;
         -> 2

所有使用的关键词必须严格以上面所显示的次序被给出。举例来说,一个 HAVING 子句必须出现在 GROUP BY 子句后,在 ORDER BY 字句之前。

  • 一个 SELECT 表达式可以使用 AS 指定一个别名。别名可以当作表达式的列名,用于 ORDER BYHAVING 子句中。例如:
    mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
        FROM mytable ORDER BY full_name;
    
  • 在一个 WHERE 子句中使用一个列别名是不允许的,因为,当 WHERE 子句被执行时,列值可能还没有被计算确定。查看章节 A.5.4 使用 alias 的限制

     

  • FROM table_references 子句表示从哪个表中检索记录行。如果你命名超过超过一个表,并执行一个 join。对于 join 句法的信息,查看章节 6.4.1.1 JOIN 句法。对于每个引用的表,你可以顺便指定一个别名。
    table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | FORCE INDEX (key_list)]]
    
    到 MySQL 3.23.12 时,当 MySQL 在从一个表中检索信息时,你可以提示它选择了哪一个索引。如果 EXPLAIN 显示 MySQL 使用了可能的索引列表中错误的索引,这个特性将是很有用的。通过指定 USE INDEX (key_list),你可以告诉 MySQL 使用可能的索引中最合适的一个索引在表中查找记录行。可选的二选一句法 IGNORE INDEX (key_list) 可被用于告诉 MySQL 不使用特定的索引。 在 MySQL 4.0.9 中,你也可以使用 FORCE INDEX。这个有点像 USE INDEX (key_list),但是有了这个附加物,一个表的扫描被采用时,将会有非常大的开销。换句法说,如果没有方法使用给定的索引在表中寻找记录行,这时表扫描才会被使用。 USE/IGNORE/FORCE KEY 分别是 USE/IGNORE/FORCE INDEX 的同义词。

     

  • 你可以以 tbl_name (在当前的数据库中) 引用一张表,或以 dbname.tbl_name 明确地指定其个数据。你要以以 col_nametbl_name.col_namedb_name.tbl_name.col_name 引用一个列。 你不需要在一个 SELECT 语句中引用的列前指定 tbl_namedb_name.tbl_name 前缀,除非引用列存在二义性。查看章节 6.1.2 数据库、表、索引、列和别名,对于有歧义的列引用需要更加显式的列引用格式。

     

  • 一个表的引用可以使用 tbl_name [AS] 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;
    
  • 选取出来用于输出的列可以在 ORDER BYGROUP BY 子句中使用列名、列的别名或列的位置来引用。列的位置从 1 开始:
    mysql> SELECT college, region, seed FROM tournament
        ->        ORDER BY region, seed;
    mysql> SELECT college, region AS r, seed AS s FROM tournament
        ->        ORDER BY r, s;
    mysql> SELECT college, region, seed FROM tournament
        ->        ORDER BY 2, 3;
    
    为了以倒序排序,可以在 ORDER BY 子句中用于排序的列名后添加一个 DESC (递减 descending)关键词。缺省为升序排序;这也可以通过使用 ASC 关键词明确指定。

     

  • WHERE 子句中可以使用 MySQL 支持的任何函数。查看章节 6.3 用于 SELECTWHERE 子句的函数

     

  • HAVING 子句可以引用任何列或在 select_expression 中命名的别名。它在最后被执行,仅仅就在项目被送到客户端之前,不进行任何优化。所以不要对应该放在 WHERE 子句中的项目使用 HAVING。举例来说,不要写成这样:
    mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;
    
    用这个代替:
    mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;
    
    在 MySQL 3.22.5 或以后的版本中,你也可以这下面的形式书写一个查询:
    mysql> SELECT user,MAX(salary) FROM users
        ->        GROUP BY user HAVING MAX(salary)>10;
    
    在较早的 MySQL 版本中,你可能需要用下面的代替了:
    mysql> SELECT user,MAX(salary) AS sum FROM users
        ->        group by user HAVING sum>10;
    
  • DISTINCTDISTINCTROWALL 选项指定重复的记录行是否被返回。缺省为 (ALL),返回所有匹配的记录行。DISTINCTDISTINCTROW 是同义词,它指定结果集重复的记录行被排除。

     

  • 所有以 SQL_ 开头、STRAIGHT_JOINHIGH_PRIORITY 的选项是 MySQL 对 ANSI SQL 的扩展。

     

  • HIGH_PRIORITY 将给 SELECT 语句比更新一个表有更高的优先级。你只应该对非常快的或需要立即返回的查询使用它。 如果一个表已被读锁定,甚至是有一个更新语句正在等待表的释放,一个 SELECT HIGH_PRIORITY 查询也将会执行。

     

  • SQL_BIG_RESULT 可以与 GROUP BYDISTINCT 一同使用,以告诉优化器结果集将有许多记录行。在这种情况下,如果需要,MySQL 将直接使用基于磁盘的临时表。同样的,在这种情况下,MySQL 更愿意以 GROUP BY 上的一个键进行排序而不是建立一个临时表。

     

  • SQL_BUFFER_RESULT 将强制把结果放入一个临时表。这将有助于 MySQL 尽早地释放表和有助于将大的结果集传送到客户端。

     

  • SQL_SMALL_RESULT, 一个 MySQL 特有的选项,可以与 GROUP BYDISTINCT 一同使用,以告诉优化器结果集将会很小。在这种情况下,MySQL 将使用快速的临时表存储结果表,而不是使用排序。在 MySQL 3.23 中,这通常是不需要的。

     

  • SQL_CALC_FOUND_ROWS (版本 4.0.0 和更新的) 告诉 MySQL 计算在不考虑 LIMIT 子句时结果集中将有多少行记录。然后使用 SELECT FOUND_ROWS() 可以检索到记录行的数目。查看章节 6.3.6.2 辅助功能函数。 请注意,在早于 4.1.0 的版本中,LIMIT 0 是不工作的,它将被优化为立即返回(结果集的记录数为 0)。查看章节 5.2.8 MySQL 如何优化 LIMIT

     

  • 如果你使用了 QUERY_CACHE_TYPE=2 (DEMAND),SQL_CACHE 告诉 MySQL 将存储查询结果放入查询高速缓存内。查看章节 6.9 MySQL 的查询高速缓存

     

  • SQL_NO_CACHE 告诉 MySQL 不允许将查询结果存储到查询缓存内。查看章节 6.9 MySQL 的查询高速缓存

     

  • 如果使用了 GROUP BY,输出记录将会依照 GROUP BY 列进行排序,就好像你对所有 GROUP BY 中的所有字段使用了 ORDER BY。MySQL 扩展了 GROUP BY 的用法,所以你也可以在 GROUP BY 中指定 ASCDESC
    SELECT a,COUNT(b) FROM test_table GROUP BY a DESC
    
  • MySQL 扩展了的 GROUP BY 用法允许你选取没有在 GROUP BY 子句中提及的字段。如果你的查询没有得到你所期望的结果,请查看 GROUP BY 中的描述。查看章节 6.3.7 用于 GROUP BY 子句的函数

     

  • STRAIGHT_JOIN 强制优化器以表在 FROM 子句中列出的顺序联结。如果优化器以一个非优化的次序联结各表,你可以使用它来加速一个查询。查看章节 5.2.1 EXPLAIN 句法(得到有关 SELECT 的信息)

     

  • LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1): 为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #
    mysql> SELECT * FROM table LIMIT 5,10;  # 检索记录行 6-15
    
    为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
    mysql> SELECT * FROM table LIMIT 95,-1; # 检索记录行 96-last.
    
    如果只给定一个参数,它表示返回最大的记录行数目:
    mysql> SELECT * FROM table LIMIT 5;     # 检索前 5 个记录行
    
    换句话说,LIMIT n 等价于 LIMIT 0,n

     

  • SELECT ... INTO OUTFILE 'file_name' 格式的 SELECT 将选择的记录行写入一个文件。文件被建立在服务器主机上,并且不可以是已存在的 (不管别的,这可以防止数据库表和文件例如 `/etc/passwd' 被破坏)。你必须在服务器主机上有 FILE 权限来使用这个形式的 SELECTSELECT ... INTO OUTFILE 主要是有意于让你能够在服务主机上快速地转储一个表。如果你希望将结果文件建立在其它的主机上,而不是服务器上,你就不能使用 SELECT ... INTO OUTFILE。在这种情况下,你应该使用某些客户端程序例如 mysqldump --tabmysql -e "SELECT ..." > outfile 产生文件来代替它。 SELECT ... INTO OUTFILELOAD DATA INFILE 的逆操作;语句中的 export_options 部分的句法由 FIELDSLINES 子句组成,它们与与用在 LOAD DATA INFILE 语句中的相同。查看章节 6.4.9 LOAD DATA INFILE 句法。 在结果文本文件中,只有下列的字符被 ESCAPED BY 指定的字符转义:
    • ESCAPED BY 字符
    • FIELDS TERMINATED BY 中的第一个字符
    • LINES TERMINATED BY 中的第一个字符
    另外,ASCII 0 被转换到 ESCAPED BY 后而跟一个 0 (ASCII 48)。 上述行为的原因是,你必须 转义任何 FIELDS TERMINATED BYESCAPED BYLINES TERMINATED BY 字符,以便能可靠地将文件读回。ASCII 0 被转义是为了更容易地使用某些分页程序查看它。 因为结果文件并不需要遵从 SQL 句法,所以其它是不需要转义。 下面的例子得到的文件是可用于许多老程序的格式。
    SELECT a,b,a+b INTO OUTFILE "/tmp/result.text"
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
    LINES TERMINATED BY "/n"
    FROM test_table;
    
  • 如果使用 INTO DUMPFILE 代替 INTO OUTFILE,MySQL 将在文件中只写一行,没任何列或行端接和任何转义。如果你希望存储一个 blob 列到文件中,这是非常有用的。
  • 注意,任何由 INTO OUTFILEINTO DUMPFILE 创建的文件将被所有用户可读写!原因是, MySQL 服务器不能够创建一个其他用户拥有的文件,(你决不应该以 root 身份运行 mysqld),该文件必须是公共可读写的,以便于你能操作它。

     

  • 如果你以页/行锁使用在一个存储引擎上 FOR UPDATE,被检索的记录行将被写锁。
6.4.1.1 JOIN 句法

MySQL 支持在 SELECT 中使用下面所示的 JOIN 句法:

table_reference, table_reference
table_reference [CROSS] JOIN table_reference
table_reference INNER JOIN table_reference join_condition
table_reference STRAIGHT_JOIN table_reference
table_reference LEFT [OUTER] JOIN table_reference join_condition
table_reference LEFT [OUTER] JOIN table_reference
table_reference NATURAL [LEFT [OUTER]] JOIN table_reference
{ OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr }
table_reference RIGHT [OUTER] JOIN table_reference join_condition
table_reference RIGHT [OUTER] JOIN table_reference
table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference

table_reference 定义如下:

table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]

join_condition 定义如下:

ON conditional_expr |
USING (column_list)

通常不应该在 ON 存在任何条件式,它是用于限制在结果集中有哪个行的(对于这个规则也有例外)。如果你希望哪个记录行应该在结果中,你必须在 WHERE 子句中限制它。

注意,在早于 3.23.17 的版本中,INNER JOIN 不接受一个 join_condition

上面所显示的最后一个 LEFT OUTER JOIN 句法仅仅是为了与 ODBC 兼容而存在的:

  • 一个表引用可以使用 tbl_name AS alias_nametbl_name alias_name 命以别名:
    mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
        ->        WHERE t1.name = t2.name;
    
  • ON 条件是可以用在一个 WHERE 子句中的任何形式的条件。

     

  • 如果在一个 LEFT JOINONUSING 部分中右表没有匹配的记录,一个所有列被设置为 NULL 的记录行将被用于右表。你可以通过这个行为找到一个表在另一个表中没有配对物的记录:
    mysql> SELECT table1.* FROM table1
        ->        LEFT JOIN table2 ON table1.id=table2.id
        ->        WHERE table2.id IS NULL;
    
    这个例子在 table1 中找到所有的记录行,其 id 值没有出现在 table2 中(即,所有在 table1 存在的,但在 table2 中没有对应记录的记录行)。当然,这是假定 table2.id 被声明为 NOT NULL 的。查看章节 5.2.6 MySQL 如何优化 LEFT JOINRIGHT JOIN

     

  • USING (column_list) 子句指定了一个列的列表,列表的中列必须同时存在于两个表中。例如 USING 子句如下所示:
    A LEFT JOIN B USING (C1,C2,C3,...)
    
    它可以被定义为在语义上等同于一个这样的 ON 表达式:
    A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
    
  • 两个表的 NATURAL [LEFT] JOIN 被定义为在语义上等同于使用了 USING 子句指定存在于两张表中的所有列的一个 INNER JOIN 或一个 LEFT JOIN

     

  • INNER JOIN, (逗号) 在语义上是等同的。都是在所有的表之间进行一个全联结。通常,在 WHERE 条件中指定表应该如何联结。

     

  • RIGHT JOIN 作用类似于 LEFT JOIN。为了保持数据库边的代码上精简,LEFT JOIN 被推荐使用来代替 RIGHT JOIN

     

  • STRAIGHT_JOIN 等同于 JOIN,除了左表先于右表被读入。当联结优化器将表的顺序放错时(很少),这可用于这种情况。

     

  • 到 MySQL 3.23.12 时,当 MySQL 在从一个表中检索信息时,你可以提示它选择了哪一个索引。如果 EXPLAIN 显示 MySQL 使用了可能的索引列表中错误的索引,这个特性将是很有用的。通过指定 USE INDEX (key_list),你可以告诉 MySQL 使用可能的索引中最合适的一个索引在表中查找记录行。可选的二选一句法 IGNORE INDEX (key_list) 可被用于告诉 MySQL 不使用特定的索引。 在 MySQL 4.0.9 中,你也可以使用 FORCE INDEX。这个有点像 USE INDEX (key_list),但是有了这个附加物,一个表的扫描被采用时,将会有非常大的开销。换句法说,如果没有方法使用给定的索引在表中寻找记录行,这时表扫描才会被使用。 USE/IGNORE/FORCE KEY 分别是 USE/IGNORE/FORCE INDEX 的同义词。

一些例子:

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;

查看章节 5.2.6 MySQL 如何优化 LEFT JOINRIGHT JOIN

6.4.1.2 UNION 句法

SELECT ...
UNION [ALL]
SELECT ...
  [UNION
   SELECT ...]

UNION 在 MySQL 4.0.0 中被实现。

UNION 用于将多个 SELECT 语句的结果联合到一个结果集中。

SELECT 中的 select_expression 部分列出的列必须具有同样的类型。第一个 SELECT 查询中使用的列名将作为结果集的列名返回。

SELECT 命令是一个普通的选择命令,但是有下列的限制:

  • 只有最后一个 SELECT 命令可以有 INTO OUTFILE

如果你不为 UNION 使用关键词 ALL,所有返回的记录行将是唯一的,就好像你为整个返回集使用了一个 DISTINCT。如果你指定了 ALL,那么你将得到从所有使用的 SELECT 语句中返回的所有匹配记录行。

如果你希望对整个 UNION 结果使用一个 ORDER BY,你应该使用圆括号:

(SELECT a FROM table_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM table_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10)
ORDER BY a;

6.4.2 HANDLER 句法

HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name CLOSE

HANDLER 语句提供了直接访问 MyISAM 表存储引擎的接口。

HANDLER 语句的第一个形式打开一个表,通过后来的 HANDLER ... READ 语句使它可读取。这个表对象将不能被其它线程共享,也不会被关闭,除非线程调用 HANDLER tbl_name CLOSE 或线程关闭。

第二个形式读取指定的索引遵从那个条件并且适合 WHERE 条件的一行(或更多的,由 LIMIT 子句指定)。如果索引由几个部分组成(范围有几个列),值以逗号分隔的列表指定;如果只提供的一部分值,那么第一个列是必需的。

第三个形式从表中以索引的顺序读取匹配 WHERE 条件的一行(或更多的,由 LIMIT 子句指定)。

第四个形式(没有索引清单)从表中以自然的列顺序(在数据文件中存储的次序)读取匹配 WHERE 条件的一行(或更多的,由 LIMIT 子句指定)。如果期望做一个全表扫描,它将比 HANDLER tbl_name READ index_name 更快。

HANDLER ... CLOSE 关闭一个以 HANDLER ... OPEN 打开的表。

HANDLER 是一个稍微低级的语句。举例来说,它不提供一致性约束。更确切地说,HANDLER ... OPEN 接受一个表的快照,并且 锁定表。这就意味着在一个 HANDLER ... OPEN 被执行后,表数据仍会被 (这个或其它的线程) 修改,这些修改可能在 HANDLER ... NEXTHANDLER ... PREV 扫描中才会部分地出现。

使用这个接口代替普通 SQL 的原因是:

  • 它比 SELECT 快,因为:
    • HANDLER OPEN 中,一个指定的存储引擎被分配给当前线程。
    • 较少的复杂解析。
    • 没有优化器和没有查询检查开销。
    • 在两个处理请求之间不需要锁定使用的表。
    • 接口处理机并不提供一个一致性的查看数据 (举例来说,读污染 dirty-reads 是允许的),因而,存储引擎可以做 SQL 通常不允许的优化。
  • 它使得更加容易地移植一个使用对 MySQL 的 ISAM 类似接口的应用程序。
  • 它允许你在一个以 SQL 不容易完成(在某些不可能的完全)的情况下遍历一个数据库。当使用提供了一个交互式的用户接口访问数据库的应用程序时,接口处理机是更加自然的查看数据的方式。

6.4.3 INSERT 句法

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        VALUES ((expression | DEFAULT),...),(...),...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]
or  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
or  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name
        SET col_name=(expression | DEFAULT), ...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]

INSERT 将新行插入到一个已存在的表中。INSERT ... VALUES 形式的语句基于明确的值插入记录行。INSERT ... SELECT 形式的语句从另一个或多个表中选取出值,并将其插入。有多重值列表的 INSERT ... VALUES 形式的语句在 MySQL 3.22.5 或更新的版本中被支持。col_name=expression 句法在 MySQL 3.22.10 或更新的版本中得到支持。

tbl_name 是记录将要被插入的表。列名列表或 SET 子句指出语句指定的值赋给哪个列:

  • 如果在 INSERT ... VALUESINSERT ... SELECT 中没有指定列列表,那么所有列的值必须在 VALUES() 列表中或由 SELECT 提供。如果你不知道表的列的次序,可以使用 DESCRIBE tbl_name 来决定它。

     

  • 任何没有明确指定一个值的列均会被设置为它的缺省值。举例来说,如果你指定的一个列列表没有指定表中所有的列,未指定的列将被设置为它们的缺省值。缺省值赋值的描述在章节 6.5.3 CREATE TABLE 句法。 你也可以使用关键词 DEFAULT 来将一个列设置为它的默认值(这在 MySQL 4.0.3 中被新加入)。这使它更加容易地书写赋予值到所有除了几列的 INSERT 语句,因为它允许您避免书写一个不完全的 VALUES() 的列表(在该列表没有包含表中的每个列的列值)。否则,你将不得不在 VALUES() 列表中写出列列表指定对应的值。 MySQL 通常都会为每个字段设置一个缺省值。这是某些强加在 MySQL 上的,在事务型表与非事务型表中均工作。 我们的观点是在应用程序端检查字段的内容,而不是在数据库服务器端。

     

  • 一个 expression 可以引用先前在值列表中设置的任何列。例如,你可以这样:
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
    
    但是不能这样:
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
    
  • 如果你指定关键词 LOW_PRIORITYINSERT 的执行将会被延迟,直到没有其它客户端正在读取表。在这种情况下,客户端不得不等待插入语句被完成,如果表被频繁地使用,那么这将会花费很长一段时间。这与 INSERT DELAYED 让客户端立即继续执行正好相反。查看章节 6.4.4 INSERT DELAYED 句法。注意,LOW_PRIORITY 通常不对 MyISAM 使用,因为这将禁止并发的插入。查看章节 7.1 MyISAM

     

  • 如果你在一个有许多条记录行值的 INSERT 中指定关键词 IGNORE,任何在表中现有的 PRIMARYUNIQUE 键上重复的记录行均会被忽略而不被插入。如果你不指定 IGNORE,当有任何记录行在一个现有的键值上重复时,插入均会被中止。你可以通过 C API 函数 mysql_info() 测定共有多少记录行被插入到表中。

     

  • 如果你指定 ON DUPLICATE KEY UPDATE 子句(在 MySQL 4.1.0 中被新加入),并且被插入的一个记录行在 PRIMARYUNIQUE 键上将会产生一个重复值,那么老的记录行将被 UPDATE。举例来说:
    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
       --> ON DUPLICATE KEY UPDATE c=c+1;
    
    假设列 a 被定义为 UNIQUE,并且已存在了一个 1,它将与下面的语句产生同样的结果:
    mysql> UPDATE table SET c=c+1 WHERE a=1;
    
    注意:如果列 b 也是唯一的,UPDATE 命令将要被写成这样:
    mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
    
    并且如果 a=1 OR b=2 匹配几个记录行,只有 一个 记录行将被更新!大体上,在有多重 UNIQUE 键的表上,你应该尽是避免使用 ON DUPLICATE KEY 子句。 当使用了 ON DUPLICATE KEY UPDATE 后,DELAYED 选项将被忽略。

     

  • 如果 MySQL 被设置为使用 DONT_USE_DEFAULT_FIELDS 选项,INSERT 语句将产生一个错误,除非你为所有需要一个非 NULL 值的列明确指定值。查看章节 2.3.3 典型的 configure 选项

     

  • 通过使用 mysql_insert_id 函数你可以找到用于一个 AUTO_INCREMENT 列的值。查看章节 8.1.3.130 mysql_insert_id()

如果你使用 INSERT ... SELECT 或一个 INSERT ... VALUES 语句插入多值列,你可以使用 C API 函数 mysql_info() 得到查询的信息。信息字串的格式如下:

Records: 100 Duplicates: 0 Warnings: 0

Duplicates 指出因与某些现有的唯一索引值重复而不能被插入的记录行数目。Warnings 指出在尝试插入的列值中在某些方面可能有问题的数目。在下列任何一个条件下,警告都会发生:

  • 向一个定义为 NOT NULL 的列中插入 NULL 值。该列被设置为它的缺省值。
  • 将一个超出列范围的值赋给一个数字列。该值被剪切到该范围内的适当的端点。
  • 将一个例如 '10.34 a' 的值赋给一个数字列。尾部的无用信息将被剥离,保留数字部分并将其插入。如果该值看起来根本就不是一个数字,该列将被设置为 0
  • 将一个超出了列最大长度的字符串插入到一个 CHARVARCHARTEXTBLOB 列中。该值将被剪切到该列的最大长度。
  • 将一个对列类型不合法的值插入到一个日期或时间列中。该列被适当格式的零值。

6.4.3.1 INSERT ... SELECT 句法
INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name [(column list)] SELECT ...

使用 INSERT ... SELECT 语句,你可以从一个或多个表中读取多个记录行,并将其快速地插入到一个表中。

INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE
tblTemp1.fldOrder_ID > 100;

一个 INSERT ... SELECT 语句有下列条件的限止:

  • INSERT 语句中的目标表不能在 SELECT 查询部分的 FROM 子句中出现,因为在 ANSI SQL 中,禁止你从正在插入的表中 SELECT。(问题是因为,SELECT 可能会发现在同一运行期内先前被插入的记录。当使用子选择子句时,这种情况将会更容易混淆!)
  • AUTO_INCREMENT 列像平常一样工作。
  • 你可以使用 C API 函数 mysql_info() 得到查询的信息。查看章节 6.4.3 INSERT 句法
  • 为了确保二进制日志可以被用于重建最初的表,MySQL 将不允许在 INSERT ... SELECT 期间并发的插入。

你当然也可以使用 REPLACE 代替 INSERT 来盖写老的记录行。

6.4.4 INSERT DELAYED 句法

INSERT DELAYED ...

INSERT 语句的 DELAYED 选项是一个 MySQL 特有的选项,如果你的客户端不能等待 INSERT 的完成,这将会是很有用的。This is a common problem when you use MySQL for logging and 当你打开日志记录使用 MySQL 并且你周期性的需花费很长时间才完成的 SELECTUPDATE 语句时,这将是一个很普遍的问题。DELAYED 在 MySQL 3.22.15 中被引入。它是 MySQL 对 ANSI SQL92 的一个扩展。

INSERT DELAYED 仅仅工作与 ISAMMyISAM 表。注意,因为 MyISAM 表支持并发的 SELECTINSERT,如果在数据文件中没有空闲的块,那你将很少需要对 MyISAM 表使用 INSERT DELAYED。查看章节 7.1 MyISAM

当你使用 INSERT DELAYED 时,客户端将立即得到一个 OK,当表不被任何其它线程使用时,该行将被插入。

使用 INSERT DELAYED 的另一个主要的好处就是,从很多客户端来的插入请求会被打包在一起并写入一个块中。这比做许多单独的插入要快的多。

注意,当前的记录行队列是被存储在内存中的,一直到他们被插入到表中。这就意味着,如果你使用强制的方法(kill -9) 杀死 mysqld,或者如果意外地死掉,任何没有写到磁盘中的记录行队列都将会丢失!

下面详细地描述当你为 INSERTREPLACE 使用 DELAYED 选项时会发生什么。在这个描述中,“线程”是遇到一个 INSERT DELAYED 命令的线程,“处理器”是处理所有对于一个特定表的 INSERT DELAYED 语句的线程。

  • 当一个线程对一个表执行一个 DELAYED 语句时,将会创建一个处理器线程用以处理对该表的所有 DELAYED 语句,除非这样的处理器已经存在。

     

  • 线程检查处理器是否已经获得了一个 DELAYED 锁;如果还没有,这告诉处理程序去获得。即使其它的线程已在表上加了一个 READWRITE 锁,也能获得 DELAYED 锁。然而,处理器将等待所有的 ALTER TABLE 锁或 FLUSH TABLES 以保证表结构是最新的。

     

  • 线程执行 INSERT 语句,但是并不将记录行写到表中,它将最终的记录行的副本放到被处理器线程管理的队列中。任何语法错误都会被线程发现并报告给客户程序。

     

  • 客户端不能报告结果记录行中重复次数或 AUTO_INCREMENT 值;它不能从服务器获得它们,因为 INSERT 早在插入操作被完成之前就返回了。如果你使用 C API,mysql_info() 函数也因同样的原因而不能获得任何有意义的信息。

     

  • 当记录行被插入到表中时,二进制的日志文件将被处理器线程更新。对于多记录行的插入,当第一个记录行被插入时,二进制日志被更新。

     

  • 当每写入 delayed_insert_limit 个记录行后,处理器检查是否仍有任何 SELECT 语句没有解决。如果是这样,处理器允许在继续之前让这些语句先执行。

     

  • 当处理器发现在它的队列中没有太多的记录行时,表将被解锁。如果在 delayed_insert_timeout 秒内没有接收到新的 INSERT DELAYED 命令,处理器线程将终止。

     

  • 如果在一个特定的处理器队列中已有超过 delayed_queue_size 个记录行未被解决,线程要求 INSERT DELAYED 等待,只到在队列中有可用空间。这样做是为了保证 mysqld 服务器对延迟内存队列不使用全部的内存。

     

  • 处理器线程在 MySQL 进程列表中的 Command 列上显示为 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 的每张表处理一个单独的线程,也是有额外的开销的。这就意味着,你应该在确定你的确需要它时才使用 INSERT DELAYED

6.4.5 UPDATE 句法

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]
    [ORDER BY ...]
    [LIMIT rows]

or

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name [, tbl_name ...]
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]

UPDATE 以新的值更新现存表中行的列。SET 子句指出要修改哪个列和他们应该给定的值。WHERE 子句如果被给出,指定哪个记录行应该被更新。否则,所有的记录行被更新。如果 ORDER BY 子句被指定,记录行将被以指定的次序更新。

如果你指定关键词 LOW_PRIORITYUPDATE 的执行将被延迟,直到没有其它的客户端正在读取表。

如果你指定关键词 IGNORE,该更新语句将不会异常中止,即使在更新过程中出现重复键错误。导致冲突的记录行将不会被更新。

如果在一个表达式中从 tbl_name 中访问一个列,UPDATE 使用列的当前值。举例来说,下面的语句设置 age 列值为它的当前值加 1 :

mysql> UPDATE persondata SET age=age+1;

UPDATE 赋值是从左到右计算的。举例来说,下列语句将 age 列设置为它的两倍,然后再加 1 :

mysql> UPDATE persondata SET age=age*2, age=age+1;

如果你设置列为其当前的值,MySQL 注意到这点,并不更新它。

UPDATE 返回实际被改变的记录行数目。在 MySQL 3.22 或更新的版本中,C API 函数 mysql_info() 返回被匹配并更新的记录行数目,以及在 UPDATE 期间发生的警告的数目。

在 MySQL 3.23 中,你可以使用 LIMIT # 来确保只有给定的记录行数目被更改。

如果一个 ORDER BY 子句被使用(从 MySQL 4.0.0 开始支持),记录行将以指定的次序被更新。这实际上只有连同 LIMIT 一起才有用。

从 MySQL 4.0.4 开始,你也可以执行一个包含多个表的 UPDATE 的操作:

UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

注意:多表 UPDATE 不可以使用 ORDER BYLIMIT

6.4.6 DELETE 句法

DELETE [LOW_PRIORITY] [QUICK] FROM table_name
       [WHERE where_definition]
       [ORDER BY ...]
       [LIMIT rows]

or

DELETE [LOW_PRIORITY] [QUICK] table_name[.*] [, table_name[.*] ...]
       FROM table-references
       [WHERE where_definition]

or

DELETE [LOW_PRIORITY] [QUICK]
       FROM table_name[.*] [, table_name[.*] ...]
       USING table-references
       [WHERE where_definition]

DELETEtable_name 中删除 where_definition 中给定条件的记录行,并返回删除的记录数目。

如果你发出一个没有 WHERE 子句的 DELETE,所有的记录行将被删除。如果你以 AUTOCOMMIT 模式执行它,那么它类似于 TRUNCATE。查看章节 6.4.7 TRUNCATE 句法。在 MySQL 3.23 中,没有一个 WHERE 子句的 DELETE 将返回零作为受影响的记录数目。

当你删除所有记录行时,如果你真的希望知道多少条记录被删除,你可以使用一个这种形式的 DELETE 语句:

mysql> DELETE FROM table_name WHERE 1>0;

注意,这将比一个没有 WHERE 子句的 DELETE FROM table_name 语句慢,因为它一次只删除一行。

如果你指定关键词 LOW_PRIORITYDELETE 的执行将被延迟,直到没有其它的客户端正在读取表。

如果你指定关键词 QUICK,那么在删除过程中存储引擎将不会归并索引叶,这可能会加速某些类型的删除操作。

MyISAM 表中,删除了的记录被放在一个链接表中维护,以后的 INSERT 操作将重新使用删除后的记录位置。为了回收闲置的空间,并减小文件尺寸,使用 OPTIMIZE TABLE 语句或 myisamchk 实用程序重新组织表。OPTIMIZE TABLE 使用比较容易,但是 myisamchk 更快点。查看章节 4.5.1 OPTIMIZE TABLE 句法 和章节 4.4.6.10 表优化

第一个多表删除格式从 MySQL 4.0.0 开始被支持。第二个多表删除格式从 MySQL 4.0.2 开始被支持。

仅仅在 FROMUSING 子句 之前 列出的表中的匹配记录行被删除。效果就是,你要以从多个表中同时删除记录行,并且同样可以有其它的表用于检索。

在表名后的 .* 仅仅是为了兼容 Access

DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

or

DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

在上面的情况下,我们仅仅从 t1t2 表中删除匹配的记录行。

如果一个 ORDER BY 子句被使用(从 MySQL 4.0.0 开始支持), 记录行将以指定的次序删除。这实际上只有连同 LIMIT 一起才有用。示例如下:

DELETE FROM somelog
WHERE user = 'jcole'
ORDER BY timestamp
LIMIT 1

这将删除匹配 WHERE 子句的,并且最早被插入(通过 timestamp 来确定)的记录行。

DELETE 语句的LIMIT rows 选项是 MySQL 特有的,它告诉服务器在控制权被返回到客户端之前可被删除的最大记录行数目。这可以用来确保一个特定的 DELETE 命令不会占用太长的时间。你可以简单地重复使用 DELETE 命令,直到被影响的记录行数目小于 LIMIT 值。

从 MySQL 4.0 开始,在 DELETE 语句中可以指定多个表,用以从一个表中删除依赖于多表中的特殊情况的记录行。然而,在一个多表删除中,不能使用 ORDER BYLIMIT

6.4.7 TRUNCATE 句法

TRUNCATE TABLE table_name

在 3.23 中,TRUNCATE TABLE 被映射为 COMMIT ; DELETE FROM table_name。查看章节 6.4.6 DELETE 句法

在下面的方式中,TRUNCATE TABLE 不同于 DELETE FROM ...

  • 删简操作撤销并重建表,这将比一个接一个地删除记录行要快得多。
  • 非事务安全的;如果存在一个活动的事务或一个有效的表锁定,你将会得到一个错误。
  • 不返回删除了的记录行数目。
  • 只要表定义文件 `table_name.frm' 是有效的,即使数据或索引文件已经被损坏,也可以通过这种方式重建表。

TRUNCATE 是一个 Oracle SQL 的扩展。

6.4.8 REPLACE句法

    REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
or  REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
or  REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name
        SET col_name=expression, col_name=expression,...

REPLACE 功能与 INSERT 完全一样,除了如果在表中存在一个老的记录与新记录在一个 UNIQUEPRIMARY KEY 上有相同的值,那么在新记录被插入之前,老的记录将被删除。查看章节 6.4.3 INSERT 句法

换句话说,你不可以从一个 REPLACE 中访问老的记录行的值。某些老的 MySQL 版本中,你或许可以这样做,但是这是一个 Bug,现在已被修正了。

为了能够使用 REPLACE,你必须有对该表的 INSERTDELETE 权限。

当你使用一个 REPLACE 时,如果新的记录行代替了老的记录行,mysql_affected_rows() 将返回 2。这是因为在新行被插入之前,重复记录行被先删除了。

这个事实使得判断 REPLACE 是否是添加一条记录还是替换一条记录很容易:检查受影响记录行的值是 1 (添加)还是 2(替换)。

注意,除非你使用一个 UNIQUE 索引或 PRIMARY KEY ,使用 REPLACE 命令是没有感觉的,因为它会仅仅执行一个 INSERT

6.4.9 LOAD DATA INFILE 句法

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [FIELDS
        [TERMINATED BY '/t']
        [[OPTIONALLY] ENCLOSED BY '']
        [ESCAPED BY '//' ]
    ]
    [LINES TERMINATED BY '/n']
    [IGNORE number LINES]
    [(col_name,...)]

LOAD DATA INFILE 语句以非常高的速度从一个文本文件中读取记录行并插入到一个表中。如果 LOCAL 关键词被指定,文件从客户端主机读取。如果 LOCAL 没有被指定,文件必须位于服务器上。(LOCAL 在 MySQL 3.22.6 或更新的版本中被支持。)

由于安全性的原因,当读取位于服务器端的文本文件时,文件必须处于数据库目录或可被所有人读取的地方。同时,为了对服务器端的文件使用 LOAD DATA INFILE,你必须在服务器主机上有 FILE 权限。查看章节 4.2.7 由 MySQL 提供的权限

在 MySQL 3.23.49 和 MySQL 4.0.2 中,只有当你没有以 --local-infile=0 选项启动 mysqld,或你没有禁止你的客户端程序支持 LOCAL的情况下,LOCAL 才会工作。查看章节 4.2.4 LOAD DATA LOCAL 的安全性问题.

如果你指定关键词 LOW_PRIORITYLOAD DATA 语句的执行将会被延迟,直到没有其它的客户端正在读取表。

如果你对一个 MyISAM 表指定关键词 CONCURRENT,那么当 LOAD DATA正在执行时,其它的线程仍可以从表中检索数据。使用这个选项时,如果同时也有其它的线程正在使用表,这当然会有一点影响 LOAD DATA 的执行性能。

使用 LOCAL 将比让服务器直接访问文件要慢一些,因为文件的内容必须从客户端主机传送到服务器主机。而在另一方面,你不再需要有 FILE 权限用于装载本地文件。

如果你使用先于 MySQL 3.23.24 的版本,你不能够以 LOAD DATA INFILE 读取一个 FIFO 。如果你需要从一个 FIFO (例如,gunzip 的输出文件) 中读取,可以使用 LOAD DATA LOCAL INFILE 代替。

你也可以使用 mysqlimport 实用程序装载数据文件;它通过发送一个 LOAD DATA INFILE 命令到服务器来动作。--local 选项使得 mysqlimport 从客户端主机读取数据文件。如果客户端与服务器支持压缩协议,你可以指定 --compress 选项,以在较慢的网络中获得更好的性能。

当从服务器主机定位文件时,服务器使用下列规则:

  • 如果给定一个完整的路径,服务器使用该路径名。
  • 如果给定一个有一个或多个前置构件的相对路径,服务器以相对服务器的数据目录搜索文件。
  • 如果给定一个没有前置构件的文件名,服务器从当前数据库的数据库目录搜寻文件。

注意,这些规则意味着,一个以 `./myfile.txt' 给出的文件是从服务器的数据目录中读取的,然而,以 `myfile.txt' 给出的一个文件是从当前数据库的数据目录下读取的。举例来说,下面的 LOAD DATA 语句从 db1 数据库目录下读取文件 `data.txt',因为 db1 是当前数据库,即使该语句明确地指定读取的文件被放入到 db2 数据库中的一个表中:

mysql> USE db1;
mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;

REPLACEIGNORE 关键词控制对与现有的记录在唯一键值上重复的记录的处理。如果你指定 REPLACE,新的记录行将替换有相同唯一键值的现有记录行。如果你指定 IGNORE,将跳过与现有的记录行在唯一键值上重复的输入记录行。如果你没有指定任何一个选项,当重复键值出现时,将会发生一个错误,文本文件的剩余部分也将被忽略。

如果你使用 LOCAL 关键词从一个本地文件中读取数据,在此操作过程中,服务器没有办法停止文件的传送,因此缺省的处理方式就好像是 IGNORE 被指定一样。

如果你在一个空的 MyISAM 表上使用 LOAD DATA INFILE,所有非唯一索引会以一个分批方式被创建(就像 REPAIR)。当有许多索引时,这通常可以使 LOAD DATA INFILE 更快一些。

LOAD DATA INFILESELECT ... INTO OUTFILE 的逆操作。查看章节 6.4.1 SELECT 句法。使用 SELECT ... INTO OUTFILE 将数据从一个数据库写到一个文件中。使用 LOAD DATA INFILE 读取文件到数据库中。两个命令的 FIELDSLINES 子句的句法是一样的。两个子句都是可选的,但是如果两个同时被指定,FIELDS 子句必须出现在 LINES 子句之前。

如果你指定一个 FIELDS 子句,它的子句 (TERMINATED BY[OPTIONALLY] ENCLOSED BYESCAPED BY) 也是可选的,不过,你必须至少指定它们中的一个。

如果你没有指定一个 FIELDS 子句,缺省的相同于如果你这样写:

FIELDS TERMINATED BY '/t' ENCLOSED BY '' ESCAPED BY '//'

如果你没有指定一个 LINES 子句,缺省的相同于如果你这样写:

LINES TERMINATED BY '/n'

换句话说,当读取输入时,缺省值导致 LOAD DATA INFILE 表现如下:

  • 在换行符处寻找行的边界。
  • 在定位符处将行分开放到字段中。
  • 不认为字段由任何引号字符封装。
  • 将有 “/” 开头的定位符、换行符或 `/' 解释为字段值的一个文字字符。

相反的,当写入输出时,缺省值导致 SELECT ... INTO OUTFILE 表现如下:

  • 在字段值间加上定位符。
  • 不用任何引号字符封装字段。
  • 使用 “/” 转义出现在字段值中的定位符、换行符或 `/' 字符实例。
  • 在行的结尾处加上换行符。

注意,为了写 FIELDS ESCAPED BY '//',你必须指定两个反斜线,该值会作为一个反斜线被读入。

IGNORE number LINES 选项可被用于忽略文件开头处的一个列名的头:

mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;

当你一前一后地使用 SELECT ... INTO OUTFILELOAD DATA INFILE 将数据从一个数据库写到一个文件中,然后再从文件中将它读入数据库中时,两个命令的字段和行处理选项必须匹配。否则,LOAD DATA INFILE 将不能正确地解释文件内容。假设你使用 SELECT ... INTO OUTFILE 以逗号分隔字段的方式将数据写入到一个文件中:

mysql> SELECT * INTO OUTFILE 'data.txt'
    ->          FIELDS TERMINATED BY ','
    ->          FROM ...;

为了将由逗号分隔的文件读回时,正确的语句应该是:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
    ->           FIELDS TERMINATED BY ',';

如果你试图用下面所示的语句读取文件,它将不会工作,因为命令 LOAD DATA INFILE 以定位符区分字段值:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
    ->           FIELDS TERMINATED BY '/t';

可能的结果是每个输入行将被解释为一个单独的字段。

LOAD DATA INFILE 也可以被用来读取从外部来源获得的文件。例如,dBASE 格式的文件,字段以逗号分隔并以双引号包围着。如果文件中的行以一个换行符终止,那么下面所示的可以说明你将用来装载文件的字段和行处理选项:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
    ->           FIELDS TERMINATED BY ',' ENCLOSED BY '"'
    ->           LINES TERMINATED BY '/n';

任何字段和行处理选项都可以指定一个空字符串('')。如果不是空的,FIELDS [OPTIONALLY] ENCLOSED BYFIELDS ESCAPED BY 值必须是一个单个字符。FIELDS TERMINATED BYLINES TERMINATED BY 值可以超过一个字符。例如,为了写入由回车换行符终止的行,或读取包含这样的行的文件,应该指定一个 LINES TERMINATED BY '/r/n' 子句。

举例来说,为了读取一个文件到一个 SQL 表中,文件以一行 %% 分隔(开玩笑的),你可以这样做:

CREATE TABLE jokes (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, joke TEXT
NOT NULL);
LOAD DATA INFILE "/tmp/jokes.txt" INTO TABLE jokes FIELDS TERMINATED BY ""
LINES TERMINATED BY "/n%%/n" (joke);

FIELDS [OPTIONALLY] ENCLOSED BY 控制字段的包围字符。对于输出 (SELECT ... INTO OUTFILE),如果你省略单词 OPTIONALLY,所有的字段被 ENCLOSED BY 字符包围。这样的一个输出文件(以一个逗号作为字段分界符)示例如下:

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a /" quote","102.20"
"4","a string containing a /", quote and comma","102.20"

如果你指定 OPTIONALLYENCLOSED BY 字符仅被作用于包围 CHARVARCHAR 字段:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a /" quote",102.20
4,"a string containing a /", quote and comma",102.20

注意,在一个字段值中出现的 ENCLOSED BY 字符,通过用 ESCAPED BY 字符作为其前缀对其转义。同时也要注意,如果你指定一个空的 ESCAPED BY 值,可能会产生不能被 LOAD DATA INFILE 正确读出的输出文件。例如,如果转义字符为空,上面显示的输出将变成如下显示的输出。请注意第四行的第二个字段,它包含一个逗号跟在一个引号后的两个字符,这(错误的)看起来像是一个字段的终止:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

对于输入,ENCLOSED BY 字符如果存在,它将从字段值的尾部被剥离。(不管 OPTIONALLY 是否被指定,都是这样;对于输入解释,OPTIONALLY 不会影响它。) 由ESCAPED BY 字符领先于 ENCLOSED BY 字符的出现,将被解释为当前字段值的一部分。另外,在字段中出现的重复的 ENCLOSED BY 字符被解释为单个 ENCLOSED BY ,只要字段本身也是以该字符开始的。例如,如果 ENCLOSED BY '"' 被指定,引号将做如下处理:

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

FIELDS ESCAPED BY 控制如何写入或读出特殊字符。如果 FIELDS ESCAPED BY 字符不是空的,它将被用于做为下列输出字符的前缀:

  • FIELDS ESCAPED BY 字符
  • FIELDS [OPTIONALLY] ENCLOSED BY 字符
  • FIELDS TERMINATED BYLINES TERMINATED BY 值的第一个字符。
  • ASCII 0 (实际上在转义字符后写上 ASCII '0',而不是一个零值字节)

如果 FIELDS ESCAPED BY 字符为空,没有字符被转义。指定一个空的转义字符可能不是一个好的主意,特别是如果你的数据字段值中包含刚才列表中的任何字符时。

对于输入,如果 FIELDS ESCAPED BY 字符不为空,该字符的出现将会被剥离,后续的字符在字面上做为字段值的一部分。除了一个转义的 “0”“N” (即,/0/N,如果转义字符为 `/')。这些序列被解释为 ASCII 0 (一个零值字节) 和 NULL。查看下面的有关 NULL 处理的规则。

关于更多的 “/” 转义句法信息,查看章节 6.1.1 文字:怎么写字符串与数字

在某些情况下,字段与行处理相互作用:

  • 如果 LINES TERMINATED BY 是一个空字符串,FIELDS TERMINATED BY 是非空的,行也用 FIELDS TERMINATED BY 终止。
  • 如果 FIELDS TERMINATED BYFIELDS ENCLOSED BY 值都是空的 (''),一个固定行(无定界符) 格式被使用。用固定行格式时,在字段之间不使用分隔符。代替的,列值的写入和读取使用列的“显示”宽度。例如,如果一个列被定义为 INT(7),列的值将使用 7 个字符的字段被写入。对于输入,列值通过读取 7 个字符来获得。固定行格式也影响对 NULL 值的处理;见下面。注意,如果你正在使用一个多字节的字符集,固定长度格式将不能工作。

NULL 值的处理有很多,取决于你所使用的 FIELDSLINES 选项:

  • 对于缺省的 FIELDSLINES 值,输出时,NULL 被写成 /N,当读入时,/N 被作为 NULL 读入(假设 ESCAPED BY 字符为 “/”)。
  • 如果 FIELDS ENCLOSED BY 是非空的,一个字段包含文字词 NULL 的,它的值做为一个 NULL 值被读入 (这不同于被 FIELDS ENCLOSED BY 包围的词 NULL,它是被作为 'NULL' 读入的)。
  • 如果 FIELDS ESCAPED BY 是空的,NULL 值被写为词 NULL
  • 用固定行格式时 (它发生于 FIELDS TERMINATED BYFIELDS ENCLOSED BY 两者均为空),NULL 被写为一个空的字符串。注意,当将表中的 NULL 值和空字符串一起写到文件中时,它们将被混淆,因为它们都是作为空字符串被写入的。如果你在文件时,需要对他们两个进行区分,你不应该使用固定行格式。

一些不能被 LOAD DATA INFILE 支持的情况:

  • 固定尺寸的记录行 (FIELDS TERMINATED BYFIELDS ENCLOSED BY 均为空) 和 BLOBTEXT 列。
  • 如果你指定一个分隔符与另一个相同,或是另一个的前缀,LOAD DATA INFILE 可能会不能正确地解释输入。例如,下列的 FIELDS 子句将会产生问题:
    FIELDS TERMINATED BY '"' ENCLOSED BY '"'
    
  • 如果 FIELDS ESCAPED BY 为空,一个字段值中包含有 FIELDS ENCLOSED BYLINES TERMINATED BYFIELDS TERMINATED BY 跟随的值时,将会引起 LOAD DATA INFILE 过早地停止读取一个字段或一行。这是因为 LOAD DATA INFILE 不能够正确地决定字段或行值在哪里结果。

下面的例子将装载 persondata 表的所有列:

mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

没有字段列被指定,因而 LOAD DATA INFILE 认为输入行包含表列中所有的字段。使用缺省的 FIELDSLINES 值。

如果你希望装载表中的某些列,那指定一个字段列表:

mysql> LOAD DATA INFILE 'persondata.txt'
    ->           INTO TABLE persondata (col1,col2,...);

如果输入文件的字段次序不同于表中列的顺序,你也必须指定一个字段列表。否则 MySQL 不知道如何将输入字段与表中的列匹配。

如果一个行有很少的字段,没有输入字段的列将被设置为缺省值。缺省值赋值在章节 6.5.3 CREATE TABLE 句法 中被描述。

一个空的字段值不同于字段值丢失的解释:

  • 对于字符串类型,列被设置为空字符串。
  • 对于数字类型,列被设置为 0
  • 对于日期和时间类型,列被设置为适合列类型的“零”值。查看章节 6.2.2 Date 和 Time 类型

注意,如果在一个 INSERTUPDATE 语句中明确地将一个空字符串赋给一个字符串、数字或日期或时间类型,你会得到与上面相同的结果。

如果对 TIMESTAMP 列指定一个 NULL 值,或者当字段列表被指定时, TIMESTAMP 在字段列表中被遗漏(仅仅第一个 TIMESTAMP 列被影响),TIMESTAMP 列会被设置为当前的日期和时间。

如果输入的记录行有太多的字段,多余的字段将被忽略,并增加警告的数目。

LOAD DATA INFILE 认为所有的输入均是字符串,因而,对于 ENUMSET 列,你不能以 INSERT 语句的形式为其设置数字值。所有的 ENUMSET 必须以字符串指定!

如果你正在使用 C API,当 LOAD DATA INFILE 查询结束时,你可以调用 API 函数 mysql_info() 获得有关查询的信息。信息串的格式如下:

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

警告会在某些情况下发生,这些情况与值通过 INSERT 语句插入时发生警告的情况一样 (查看章节 6.4.3 INSERT 句法),但是 LOAD DATA INFILE 有一点与它不一样,当在输入行中有太多或过少的字段,它也会产生警告。警告不会被存储在任何地主;警告的数目仅能表示一切是否顺利。如果得到警告,并希望确切地知道为什么会得到它们,一个方法就是使用 SELECT ... INTO OUTFILE,将它保存到另外一个文件中,并与原先的输入文件进行比较。

如果你需要 LOAD DATA 从一个管道中读取,你可以使用下面的技巧:

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

如果你使用的版本早于 MySQL 3.23.25,你只能通过 LOAD DATA LOCAL INFILE 来执行上面。

有关 INSERT 相对 LOAD DATA INFILE 的效率和加快 LOAD DATA INFILE 的更多信息,请查看章节 5.2.9 INSERT 查询的速度

6.4.10 DO 句法

DO expression, [expression, ...]

执行表达式,但不返回任何结果。这是 SELECT expression, expression 的一个缩写,但是当你并不关心结果时,它稍有点优势,因为它稍稍快一点。

这主要有益于有副作用的函数,比如 RELEASE_LOCK

 
MySQL 5.1参考手册 目录 前言 1. 一般信息 1.1. 关于本手册 1.2. 本手册采用的惯例 1.3. MySQL AB概述 1.4. MySQL数据库管理系统概述 1.4.1. MySQL的历史 1.4.2. MySQL的的主要特性 1.4.3. MySQL稳定性 1.4.4. MySQL表最大能达到多少 1.4.5. 2000年兼容性 1.5. MaxDB数据库管理系统概述 1.5.1. 什么是MaxDB? 1.5.2. MaxDB的历史 1.5.3. MaxDB的特性 1.5.4. 许可和支持 1.5.5. MaxDB和MySQL之间的特性差异 1.5.6. MaxDB和MySQL之间的协同性 1.5.7. 与MaxDB有关的链接 1.6. MySQL发展大事记 1.6.1. MySQL 5.1的新特性 1.7. MySQL信息源 1.7.1. MySQL邮件列表 1.7.2. IRC(在线聊天系统)上的MySQL社区支持 1.7.3. MySQL论坛上的MySQL社区支持 1.8. MySQL标准的兼容性 1.8.1. MySQL遵从的标准是什么 1.8.2. 选择SQL模式 1.8.3. 在ANSI模式下运行MySQL 1.8.4. MySQL对标准SQL的扩展 1.8.5. MySQL与标准SQL的差别 1.8.6. MySQL处理约束的方式 2. 安装MySQL 2.1. 一般安装问题 2.1.1. MySQL支持的操作系统 2.1.2. 选择要安装的MySQL分发版 2.1.3. 怎样获得MySQL 2.1.4. 通过MD5校验和或GnuPG验证软件包的完整性 2.1.5. 安装布局 2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装Zip文件安装MySQL 2.3.7. 提取安装档案文件 2.3.8. 创建选项文件 2.3.9. 选择MySQL服务器类型 2.3.10. 首次启动服务器 2.3.11. 从Windows命令行启动MySQL 2.3.12. 以Windows服务方式启动MySQL 2.3.13. 测试MySQL安装 2.3.14. 在Windows环境下对MySQL安装的故障诊断与排除 2.3.15. 在Windows下升级MySQL 2.3.16. Windows版MySQL同Unix版MySQL对比 2.4. 在Linux下安装MySQL 2.5.在Mac OS X中安装MySQL 2.6. 在NetWare中安装MySQL 2.7. 在其它类Unix系统中安装MySQL 2.8. 使用源码分发版安装MySQL 2.8.1. 源码安装概述 2.8.2. 典型配置选项 2.8.3. 从开发源码树安装 2.8.4. 处理MySQL编译问题 2.8.5. MIT-pthreads注意事项 2.8.6. 在Windows下从源码安装MySQL 2.8.7. 在Windows下编译MySQL客户端 2.9. 安装后的设置和测试 2.9.1. Windows下安装后的过程 2.9.2. Unix下安装后的过程 2.9.3. 使初始MySQL账户安全 2.10. 升级MySQL 2.10.1. 从5.0版升级 2.10.2. 升级授权表 2.10.3. 将MySQL数据库拷贝到另一台机器 2.11. 降级MySQL 2.12. 具体操作系统相关的注意事项 2.12.1. Linux注意事项 2.12.2. Mac OS X注意事项 2.12.3. Solaris注意事项 2.12.4. BSD注意事项 2.12.5. 其它Unix注意事项 2.12.6. OS/2注意事项 2.13. Perl安装注意事项 2.13.1. 在Unix中安装Perl 2.13.2. 在Windows下安装ActiveState Perl 2.13.3. 使用Perl DBI/DBD接口的问题 3. 教程 3.1. 连接与断开服务器 3.2. 输入查询 3.3. 创建并使用数据库 3.3.1. 创建并选择数据库 3.3.2. 创建表 3.3.3. 将数据装入表中 3.3.4. 从表检索信息 3.4. 获得数据库和表的信息 3.5. 在批处理模式下使用mysql 3.6. 常用查询的例子 3.6.1. 列的最大值 3.6.2. 拥有某个列的最大值的行 3.6.3. 列的最大值:按组 3.6.4. 拥有某个字段的组间最大值的行 3.6.5. 使用用户变量 3.6.6. 使用外键 3.6.7. 根据两个键搜索 3.6.8. 根据天计算访问量 3.6.9. 使用AUTO_INCREMENT 3.7. 孪生项目的查询 3.7.1. 查找所有未分发的孪生项 3.7.2. 显示孪生对状态的表 3.8. 与Apache一起使用MySQL 4. MySQL程序概述 4.1. MySQL程序概述 4.2. 调用MySQL程序 4.3. 指定程序选项 4.3.1. 在命令行上使用选项 4.3.2. 使用选项文件 4.3.3. 用环境变量指定选项 4.3.4. 使用选项设置程序变量 5. 数据库管理 5.1. MySQL服务器和服务器启动脚本 5.1.1. 服务器端脚本和实用工具概述 5.1.2. mysqld-max扩展MySQL服务器 5.1.3. mysqld_safe:MySQL服务器启动脚本 5.1.4. mysql.server:MySQL服务器启动脚本 5.1.5. mysqld_multi:管理多个MySQL服务器的程序 5.2. mysqlmanager:MySQL实例管理器 5.2.1. 用MySQL实例管理器启动MySQL服务器 5.2.2. 连接到MySQL实例管理器并创建用户账户 5.2.3. MySQL实例管理器命令行选项 5.2.4. MySQL实例管理器配置文件 5.2.5. MySQL实例管理器识别的命令 5.3. mysqld:MySQL服务器 5.3.1. mysqld命令行选项 5.3.2. SQL服务器模式 5.3.3. 服务器系统变量 5.3.4. 服务器状态变量 5.4. mysql_fix_privilege_tables:升级MySQL系统表 5.5. MySQL服务器关机进程 5.6. 一般安全问题 5.6.1. 通用安全指南 5.6.2. 使MySQL在攻击者面前保持安全 5.6.3. Mysqld安全相关启动选项 5.6.4. LOAD DATA LOCAL安全问题 5.7. MySQL访问权限系统 5.7.1. 权限系统的作用 5.7.2. 权限系统工作原理 5.7.3. MySQL提供的权限 5.7.4. 与MySQL服务器连接 5.7.5. 访问控制, 阶段1:连接核实 5.7.6. 访问控制, 阶段2:请求核实 5.7.7. 权限更改何时生效 5.7.8. 拒绝访问错误的原因 5.7.9. MySQL 4.1中的密码哈希处理 5.8. MySQL用户账户管理 5.8.1. MySQL用户名和密码 5.8.2. 向MySQL增加新用户账户 5.8.3. 从MySQL删除用户账户 5.8.4. 限制账户资源 5.8.5. 设置账户密码 5.8.6. 使你的密码安全 5.8.7. 使用安全连接 5.9. 备份与恢复 5.9.1. 数据库备份 5.9.2. 示例用备份与恢复策略 5.9.3. 自动恢复 5.9.4. 表维护和崩溃恢复 5.9.5. myisamchk:MyISAM表维护实用工具 5.9.6. 建立表维护计划 5.9.7. 获取关于表的信息 5.10. MySQL本地化和国际应用 5.10.1. 数据和排序用字符集 5.10.2. 设置错误消息语言 5.10.3. 添加新的字符集 5.10.4. 字符定义数组 5.10.5. 字符串比较支持 5.10.6. 多字节字符支持 5.10.7. 字符集问题 5.10.8. MySQL服务器时区支持 5.11. MySQL日志文件 5.11.1. 错误日志 5.11.2. 通用查询日志 5.11.3. 二进制日志 5.11.4. 慢速查询日志 5.11.5. 日志文件维护 5.12. 在同一台机器上运行多个MySQL服务器 5.12.1. 在Windows下运行多个服务器 5.12.2. 在Unix中运行多个服务器 5.12.3. 在多服务器环境中使用客户端程序 5.13. MySQL查询高速缓冲 5.13.1. 查询高速缓冲如何工作 5.13.2. 查询高速缓冲SELECT选项 5.13.3. 查询高速缓冲配置 5.13.4. 查询高速缓冲状态和维护 6. MySQL中的复制 6.1. 复制介绍 6.2. 复制实施概述 6.3. 复制实施细节 6.3.1. 复制主线程状态 6.3.2. 复制从I/O线程状态 6.3.3. 复制从SQL线程状态 6.3.4. 复制传递和状态文件 6.4. 如何设置复制 6.5. 不同MySQL版本之间的复制兼容性 6.6. 升级复制设置 6.6.1. 将复制升级到5.0版 6.7. 复制特性和已知问题 6.8. 复制启动选项 6.9. 复制FAQ 6.10. 复制故障诊断与排除 6.11. 通报复制缺陷 6.12. 多服务器复制中的Auto-Increment 7. 优化 7.1. 优化概述 7.1.1. MySQL设计局限与折衷 7.1.2. 为可移植性设计应用程序 7.1.3. 我们已将MySQL用在何处? 7.1.4. MySQL基准套件 7.1.5. 使用自己的基准 7.2. 优化SELECT语句和其它查询 7.2.1. EXPLAIN语法(获取SELECT相关信息) 7.2.2. 估计查询性能 7.2.3. SELECT查询的速度 7.2.4. MySQL怎样优化WHERE子句 7.2.5. 范围优化 7.2.6. 索引合并优化 7.2.7. MySQL如何优化IS NULL 7.2.8. MySQL如何优化DISTINCT 7.2.9. MySQL如何优化LEFT JOIN和RIGHT JOIN 7.2.10. MySQL如何优化嵌套Join 7.2.11. MySQL如何简化外部联合 7.2.12. MySQL如何优化ORDER BY 7.2.13. MySQL如何优化GROUP BY 7.2.14. MySQL如何优化LIMIT 7.2.15. 如何避免表扫描 7.2.16. INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 7.4.2. 使你的数据尽可能小 7.4.3. 列索引 7.4.4. 多列索引 7.4.5. MySQL如何使用索引 7.4.6. MyISAM键高速缓冲 7.4.7. MyISAM索引统计集合 7.4.8. MySQL如何计算打开的表 7.4.9. MySQL如何打开和关闭表 7.4.10. 在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 7.5.6. MySQL如何使用DNS 7.6. 磁盘事宜 7.6.1. 使用符号链接 8. 客户端和实用工具程序 8.1. 客户端脚本和实用工具概述 8.2. myisampack:生成压缩、只读MyISAM表 8.3. mysqlMySQL命令行工具 8.3.1. 选项 8.3.2. mysql命令 8.3.3. 怎样从文本文件执行SQL语句 8.3.4. mysql技巧 8.4. mysqlaccess:用于检查访问权限的客户端 8.5. mysqladmin:用于管理MySQL服务器的客户端 8.6. mysqlbinlog:用于处理二进制日志文件的实用工具 8.7. mysqlcheck:表维护和维修程序 8.8. mysqldump:数据库备份程序 8.9. mysqlhotcopy:数据库备份程序 8.10. mysqlimport:数据导入程序 8.11. mysqlshow-显示数据库、表和列信息 8.12. myisamlog:显示MyISAM日志文件内容 8.13. perror:解释错误代码 8.14. replace:字符串替换实用工具 8.15. mysql_zap:杀死符合某一模式的进程 9. 语言结构 9.1. 文字值 9.1.1. 字符串 9.1.2. 数值 9.1.3. 十六进制值 9.1.4. 布尔值 9.1.5. 位字段值 9.1.6. NULL值 9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规字符集和校对 10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符集和校对 10.3.7. 字符串文字字符集和校对 10.3.8. 在SQL语句中使用COLLATE 10.3.9. COLLATE子句优先 10.3.10. BINARY操作符 10.3.11. 校对确定较为复杂的一些特殊情况 10.3.12. 校对必须适合字符集 10.3.13. 校对效果的示例 10.4. 字符集支持影响到的操作 10.4.1. 结果字符串 10.4.2. CONVERT() 10.4.3. CAST() 10.4.4. SHOW语句 10.5. Unicode支持 10.6. 用于元数据的UTF8 10.7. 与其它DBMS的兼容性 10.8. 新字符集配置文件格式 10.9. 国家特有字符集 10.10. MySQL支持的字符集和校对 10.10.1. Unicode字符集 10.10.2. 西欧字符集 10.10.3. 中欧字符集 10.10.4. 南欧与中东字符集 10.10.5. 波罗的海字符集 10.10.6. 西里尔字符集 10.10.7. 亚洲字符集 11. 列类型 11.1. 列类型概述 11.1.1. 数值类型概述 11.1.2. 日期和时间类型概述 11.1.3. 字符串类型概述 11.2. 数值类型 11.3. 日期和时间类型 11.3.1. DATETIME、DATE和TIMESTAMP类型 11.3.2. TIME类型 11.3.3. YEAR类型 11.3.4. Y2K事宜和日期类型 11.4. String类型 11.4.1. CHAR和VARCHAR类型 11.4.2. BINARY和VARBINARY类型 11.4.3. BLOB和TEXT类型 11.4.4. ENUM类型 11.4.5. SET类型 11.5. 列类型存储需求 11.6. 选择正确的列类型 11.7. 使用来自其他数据库引擎的列类型 12. 函数和操作符 12.1. 操作符 12.1.1. 操作符优先级 12.1.2. 圆括号 12.1.3. 比较函数和操作符 12.1.4. 逻辑操作符 12.2. 控制流程函数 12.3. 字符串函数 12.3.1. 字符串比较函数 12.4. 数值函数 12.4.1. 算术操作符 12.4.2. 数学函数 12.5. 日期和时间函数 12.6. MySQL使用什么日历? 12.7. 全文搜索功能 12.7.1. 布尔全文搜索 12.7.2. 全文搜索带查询扩展 12.7.3. 全文停止字 12.7.4. 全文限定条件 12.7.5. 微调MySQL全文搜索 12.8. Cast函数和操作符 12.9. 其他函数 12.9.1. 位函数 12.9.2. 加密函数 12.9.3. 信息函数 12.9.4. 其他函数 12.10. 与GROUP BY子句同时使用的函数和修改程序 12.10.1. GROUP BY(聚合)函数 12.10.2. GROUP BY修改程序 12.10.3. 具有隐含字段的GROUP BY 13. SQL语句语法 13.1. 数据定义语句 13.1.1. ALTER DATABASE语法 13.1.2. ALTER TABLE语法 13.1.3. CREATE DATABASE语法 13.1.4. CREATE INDEX语法 13.1.5. CREATE TABLE语法 13.1.6. DROP DATABASE语法 13.1.7. DROP INDEX语法 13.1.8. DROP TABLE语法 13.1.9. RENAME TABLE语法 13.2. 数据操作语句 13.2.1. DELETE语法 13.2.2. DO语法 13.2.3. HANDLER语法 13.2.4. INSERT语法 13.2.5. LOAD DATA INFILE语法 13.2.6. REPLACE语法 13.2.7. SELECT语法 13.2.8. Subquery语法 13.2.9. TRUNCATE语法 13.2.10. UPDATE语法 13.3. MySQL实用工具语句 13.3.1. DESCRIBE语法(获取有关列的信息) 13.3.2. USE语法 13.4. 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事务 13.5. 数据库管理语句 13.5.1. 账户管理语句 13.5.2. 表维护语句 13.5.3. SET语法 13.5.4. SHOW语法 13.5.5. 其它管理语句 13.6. 复制语句 13.6.1. 用于控制主服务器的SQL语句 13.6.2. 用于控制从服务器的SQL语句 13.7. 用于预处理语句的SQL语法 14. 插件式存储引擎体系结构 14.1. 前言 14.2. 概述 14.3. 公共MySQL数据库服务器层 14.4. 选择存储引擎 14.5. 将存储引擎指定给表 14.6. 存储引擎和事务 14.7. 插入存储引擎 14.8. 拔出存储引擎 14.9. 插件式存储器的安全含义 15. 存储引擎和表类型 15.1. MyISAM存储引擎 15.1.1. MyISAM启动选项 15.1.2. 键所需的空间 15.1.3. MyISAM表的存储格式 15.1.4. MyISAM表方面的问题 15.2. InnoDB存储引擎 15.2.1. InnoDB概述 15.2.2. InnoDB联系信息 15.2.3. InnoDB配置 15.2.4. InnoDB启动选项 15.2.5. 创建InnoDB表空间 15.2.6. 创建InnoDB表 15.2.7. 添加和删除InnoDB数据和日志文件 15.2.8. InnoDB数据库的备份和恢复 15.2.9. 将InnoDB数据库移到另一台机器上 15.2.10. InnoDB事务模型和锁定 15.2.11. InnoDB性能调节提示 15.2.12. 多版本的实施 15.2.13. 表和索引结构 15.2.14. 文件空间管理和磁盘I/O 15.2.15. InnoDB错误处理 15.2.16. 对InnoDB表的限制 15.2.17. InnoDB故障诊断与排除 15.3. MERGE存储引擎 15.3.1. MERGE表方面的问题 15.4. MEMORY (HEAP)存储引擎 15.5. BDB (BerkeleyDB)存储引擎 15.5.1. BDB支持的操作系统 15.5.2. 安装BDB 15.5.3. BDB启动选项 15.5.4. BDB表的特性 15.5.5. 修改BDB所需的事宜 15.5.6. 对BDB表的限制 15.5.7. 使用BDB表时可能出现的错误 15.6. EXAMPLE存储引擎 15.7. FEDERATED存储引擎 15.7.1. 安装FEDERATED存储引擎 15.7.2. FEDERATED存储引擎介绍 15.7.3. 如何使用FEDERATED表 15.7.4. FEDERATED存储引擎的局限性 15.8. ARCHIVE存储引擎 15.9. CSV存储引擎 15.10. BLACKHOLE存储引擎 16. 编写自定义存储引擎 16.1. 前言 16.2. 概述 16.3. 创建存储引擎源文件 16.4. 创建handlerton 16.5. 对处理程序进行实例化处理 16.6. 定义表扩展 16.7. 创建表 16.8. 打开表 16.9. 实施基本的表扫描功能 16.9.1. 实施store_lock()函数 16.9.2. 实施external_lock()函数 16.9.3. 实施rnd_init()函数 16.9.4. 实施info()函数 16.9.5. 实施extra()函数 16.9.6. 实施rnd_next()函数 16.10. 关闭表 16.11. 为存储引擎添加对INSERT的支持 16.12. 为存储引擎添加对UPDATE的支持 16.13. 为存储引擎添加对DELETE的支持 16.14. API引用 16.14.1. bas_ext 16.14.2. close 16.14.3. create 16.14.4. delete_row 16.14.5. delete_table 16.14.6. external_lock 16.14.7. extra 16.14.8. info 16.14.9. open 16.14.10. rnd_init 16.14.11. rnd_next 16.14.12. store_lock 16.14.13. update_row 16.14.14. write_row 17. MySQL簇 17.1. MySQL簇概述 17.2. MySQL簇的基本概念 17.3. 多计算机的简单基础知识 17.3.1. 硬件、软件和联网 17.3.2. 安装 17.3.3. 配置 17.3.4. 首次启动 17.3.5. 加载示例数据并执行查询 17.3.6. 安全关闭和重启 17.4. MySQL簇的配置 17.4.1. 从源码创建MySQL簇 17.4.2. 安装软件 17.4.3. MySQL簇的快速测试设置 17.4.4. 配置文件 17.5. MySQL簇中的进程管理 17.5.1. 用于MySQL簇的MySQL服务器进程使用 17.5.2. ndbd,存储引擎节点进程 17.5.3. ndb_mgmd,“管理服务器”进程 17.5.4. ndb_mgm,“管理客户端”进程 17.5.5. 用于MySQL簇进程的命令选项 17.6. MySQL簇的管理 17.6.1. MySQL簇的启动阶段 17.6.2. “管理客户端”中的命令 17.6.3. MySQL簇中生成的事件报告 17.6.4. 单用户模式 17.6.5. MySQL簇的联机备份 17.7. 使用与MySQL簇的高速互连 17.7.1. 配置MySQL簇以使用SCI套接字 17.7.2. 理解簇互连的影响 17.8. MySQL簇的已知限制 17.9. MySQL簇发展的重要历程 17.9.1. MySQL 5.0中的MySQL簇变化 17.9.2. 关于MySQL簇的MySQL 5.1发展历程 17.10. MySQL簇常见问题解答 17.11. MySQL簇术语表 18. 分区 18.1. MySQL中的分区概述 18.2. 分区类型 18.2.1. RANGE分区 18.2.2. LIST分区 18.2.3. HASH分区 18.2.4. KEY分区 18.2.5. 子分区 18.2.6. MySQL分区处理NULL值的方式 18.3. 分区管理 18.3.1. RANGE和LIST分区的管理 18.3.2. HASH和KEY分区的管理 18.3.3. 分区维护 18.3.4. 获取关于分区的信息 19. MySQL中的空间扩展 19.1. 前言 19.2. OpenGIS几何模型 19.2.1. Geometry类的层次 19.2.2. 类Geometry 19.2.3. 类Point 19.2.4. 类Curve 19.2.5. 类LineString 19.2.6. 类Surface 19.2.7. 类Polygon 19.2.8. 类GeometryCollection 19.2.9. 类MultiPoint 19.2.10. 类MultiCurve 19.2.11. 类MultiLineString 19.2.12. 类MultiSurface 19.2.13. 类MultiPolygon 19.3. 支持的空间数据格式 19.3.1. 著名的文本(WKT)格式 19.3.2. 著名的二进制(WKB)格式 19.4. 创建具备空间功能的MySQL数据库 19.4.1. MySQL空间数据类型 19.4.2. 创建空间值 19.4.3. 创建空间列 19.4.4. 填充空间列 19.4.5. 获取空间数据 19.5. 分析空间信息 19.5.1. Geometry格式转换函数 19.5.2. Geometry函数 19.5.3. 从已有Geometry创建新Geometry的函数 19.5.4. 测试几何对象间空间关系的函数 19.5.5. 关于几何最小边界矩形(MBR)的关系 19.5.6. 测试几何类之间空间关系的函数 19.6. 优化空间分析 19.6.1. 创建空间索引 19.6.2. 使用空间索引 19.7. MySQL的一致性和兼容性 19.7.1. 尚未实施的GIS特性 20. 存储程序和函数 20.1. 存储程序和授权表 20.2. 存储程序的语法 20.2.1. CREATE PROCEDURE和CREATE FUNCTION 20.2.2. ALTER PROCEDURE和ALTER FUNCTION 20.2.3. DROP PROCEDURE和DROP FUNCTION 20.2.4. SHOW CREATE PROCEDURE和SHOW CREATE FUNCTION 20.2.5. SHOW PROCEDURE STATUS和SHOW FUNCTION STATUS 20.2.6. CALL语句 20.2.7. BEGIN ... END复合语句 20.2.8. DECLARE语句 20.2.9. 存储程序中的变量 20.2.10. 条件和处理程序 20.2.11. 光标 20.2.12. 流程控制构造 20.3. 存储程序、函数、触发程序和复制:常见问题 20.4. 存储子程序和触发程序的二进制日志功能 21. 触发程序 21.1. CREATE TRIGGER语法 21.2. DROP TRIGGER语法 21.3. 使用触发程序 22. 视图 22.1. ALTER VIEW语法 22.2. CREATE VIEW语法 22.3. DROP VIEW语法 22.4. SHOW CREATE VIEW语法 23. INFORMATION_SCHEMA信息数据库 23.1. INFORMATION_SCHEMA表 23.1.1. INFORMATION_SCHEMA SCHEMATA表 23.1.2. INFORMATION_SCHEMA TABLES表 23.1.3. INFORMATION_SCHEMA COLUMNS表 23.1.4. INFORMATION_SCHEMA STATISTICS表 23.1.5. INFORMATION_SCHEMA USER_PRIVILEGES表 23.1.6. INFORMATION_SCHEMA SCHEMA_PRIVILEGES表 23.1.7. INFORMATION_SCHEMA TABLE_PRIVILEGES表 23.1.8. INFORMATION_SCHEMA COLUMN_PRIVILEGES表 23.1.9. INFORMATION_SCHEMA CHARACTER_SETS表 23.1.10. INFORMATION_SCHEMA COLLATIONS表 23.1.11. INFORMATION_SCHEMA COLLATION_CHARACTER_SET_APPLICABILITY表 23.1.12. INFORMATION_SCHEMA TABLE_CONSTRAINTS表 23.1.13. INFORMATION_SCHEMA KEY_COLUMN_USAGE表 23.1.14. INFORMATION_SCHEMA ROUTINES表 23.1.15. INFORMATION_SCHEMA VIEWS表 23.1.16. INFORMATION_SCHEMA TRIGGERS表 23.1.17. 其他INFORMATION_SCHEMA表 23.2. SHOW语句的扩展 24. 精度数学 24.1. 数值的类型 24.2. DECIMAL数据类型更改 24.3. 表达式处理 24.4. 四舍五入 24.5. 精度数学示例 25. API和库 25.1. libmysqld,嵌入式MySQL服务器库 25.1.1. 嵌入式MySQL服务器库概述 25.1.2. 使用libmysqld编译程序 25.1.3. 使用嵌入式MySQL服务器时的限制 25.1.4. 与嵌入式服务器一起使用的选项 25.1.5. 嵌入式服务器中尚需完成的事项(TODO) 25.1.6. 嵌入式服务器示例 25.1.7. 嵌入式服务器的许可 25.2. MySQL C API 25.2.1. C API数据类型 25.2.2. C API函数概述 25.2.3. C API函数描述 25.2.4. C API预处理语句 25.2.5. C API预处理语句的数据类型 25.2.6. C API预处理语句函数概述 25.2.7. C API预处理语句函数描述 25.2.8. C API预处理语句方面的问题 25.2.9. 多查询执行的C API处理 25.2.10. 日期和时间值的C API处理 25.2.11. C API线程函数介绍 25.2.12. C API嵌入式服务器函数介绍 25.2.13. 使用C API时的常见问题 25.2.14. 创建客户端程序 25.2.15. 如何生成线程式客户端 25.3. MySQL PHP API 25.3.1. 使用MySQL和PHP的常见问题 25.4. MySQL Perl API 25.5. MySQL C++ API 25.5.1. Borland C++ 25.6. MySQL Python API 25.7. MySQL Tcl API 25.8. MySQL Eiffel Wrapper 25.9. MySQL程序开发实用工具 25.9.1. msql2mysql:转换mSQL程序以用于MySQL 25.9.2. mysql_config:获取编译客户端的编译选项 26. 连接器 26.1. MySQL Connector/ODBC 26.1.1. MyODBC介绍 26.1.2. 关于ODBC和MyODBC的一般信息 26.1.3. 如何安装MyODBC 26.1.4. 在Windows平台上从二进制版本安装MyODBC 26.1.5. I在Unix平台上从二进制版本安装MyODBC 26.1.6. 在Windows平台上从源码版本安装MyODBC 26.1.7. 在Unix平台上从源码版本安装MyODBC 26.1.8. 从BitKeeper开发源码树安装MyODBC 26.1.9. MyODBC配置 26.1.10. 与MyODBC连接相关的事宜 26.1.11. MyODBC和Microsoft Access 26.1.12. MyODBC和Microsoft VBA及ASP 26.1.13. MyODBC和第三方ODBC工具 26.1.14. MyODBC通用功能 26.1.15. 基本的MyODBC应用步骤 26.1.16. MyODBC API引用 26.1.17. MyODBC数据类型 26.1.18. MyODBC错误代码 26.1.19. MyODBC与VB:ADO、DAO和RDO 26.1.20. MyODBC与Microsoft.NET 26.1.21. 感谢 26.2. MySQL Connector/NET 26.2.1. 前言 26.2.2. 下载并安装MySQL Connector/NET 26.2.3. Connector/NET体系结构 26.2.4. 使用MySQL Connector/NET 26.2.5. MySQL Connector/NET变更史 26.3. MySQL Connector/J 26.3.1. 基本的JDBC概念 26.3.2. 安装 Connector/J 26.3.3. JDBC引用 26.3.4. 与J2EE和其他Java框架一起使用 Connector/J 26.3.5. 诊断 Connector/J方面的问题 26.3.6. Changelog 26.4. MySQL Connector/MXJ 26.4.1. 前言 26.4.2. 支持平台: 26.4.3. Junit测试要求 26.4.4. 运行Junit测试 26.4.5. 作为JDBC驱动程序的一部分运行 26.4.6. 在Java对象中运行 26.4.7. MysqldResource API 26.4.8. 在JMX代理(custom)中运行 26.4.9. 部署在标准的JMX代理环境下 (JBoss) 26.4.10. 安装 27. 扩展MySQL 27.1. MySQL内部控件 27.1.1. MySQL线程 27.1.2. MySQL测试套件 27.2. 为MySQL添加新函数 27.2.1. 自定义函数接口的特性 27.2.2. CREATE FUNCTION/DROP FUNCTION语法 27.2.3. 添加新的自定义函数 27.2.4. 添加新的固有函数 27.3. 为MySQL添加新步骤 27.3.1. 步骤分析 27.3.2. 编写步骤 A. 问题和常见错误 A.1. 如何确定导致问题的原因 A.2. 使用MySQL程序时的常见错误 A.2.1. 拒绝访问 A.2.2. 无法连接到[local] MySQL服务器 A.2.3. 客户端不支持鉴定协议 A.2.4. 输入密码时出现密码错误 A.2.5. 主机的host_name被屏蔽 A.2.6. 连接数过多 A.2.7. 内存溢出 A.2.8. MySQL服务器不可用 A.2.9. 信息包过大 A.2.10. 通信错误和失效连接 A.2.11. 表已满 A.2.12. 无法创建文件/写入文件 A.2.13. 命令不同步 A.2.14. 忽略用户 A.2.15. 表tbl_name不存在 A.2.16. 无法初始化字符集 A.2.17. 文件未找到 A.3. 与安装有关的事宜 A.3.1. 与MySQL客户端库的链接问题 A.3.2. 如何以普通用户身份运行MySQL A.3.3. 与文件许可有关的问题 A.4. 与管理有关的事宜 A.4.1. 如何复位根用户密码 A.4.2. 如果MySQL依然崩溃,应作些什么 A.4.3. MySQL处理磁盘满的方式 A.4.4. MySQL将临时文件储存在哪里 A.4.5. 如何保护或更改MySQL套接字文件/tmp/mysql.sock A.4.6. 时区问题 A.5. 与查询有关的事宜 A.5.1. 搜索中的大小写敏感性 A.5.2. 使用DATE列方面的问题 A.5.3. 与NULL值有关的问题 A.5.4. 与列别名有关的问题 A.5.5. 非事务表回滚失败 A.5.6. 从相关表删除行 A.5.7. 解决与不匹配行有关的问题 A.5.8. 与浮点比较有关的问题 A.6. 与优化器有关的事宜 A.7. 与表定义有关的事宜 A.7.1. 与ALTER TABLE有关的问题 A.7.2. 如何更改表中的列顺序 A.7.3. TEMPORARY TABLE问题 A.8. MySQL中的已知事宜 A.8.1. MySQL中的打开事宜 B. 错误代码和消息 B.1. 服务器错误代码和消息 B.2. 客户端错误代码和消息 C. 感谢 C.1. MySQL AB处的开发人 C.2. MySQL贡献人 C.3. 资料员和译员 C.4. MySQL使用和包含的库 C.5. 支持MySQL的软件包 C.6. 用于创建MySQL的工具 C.7. MySQL支持人员 D. MySQL变更史 D.1. 5.1.x版中的变更情况(开发) D.1.1. 5.1.2版中的变更情况(尚未发布) D.1.2. 5.1.1版中的变更情况(尚未发布) D.2. MyODBC的变更情况 D.2.1. MyODBC 3.51.12的变更情况 D.2.2. MyODBC 3.51.11的变更情况 E. 移植到其他系统 E.1. 调试MySQL服务器 E.1.1. 针对调试编译MySQL E.1.2. 创建跟踪文件 E.1.3. 在gdb环境下调试mysqld E.1.4. 使用堆栈跟踪 E.1.5. 使用日志文件找出mysqld中的错误原因 E.1.6. 如果出现表崩溃,请生成测试案例 E.2. 调试MySQL客户端 E.3. DBUG软件包 E.4. 关于RTS线程的注释 E.5. 线程软件包之间的差异 F. 环境变量 G. MySQL正则表达式 H. MySQL中的限制 H.1. 联合的限制 I. 特性限制 I.1. 对存储子程序和触发程序的限制 I.2. 对服务器端光标的限制 I.3. 对子查询的限制 I.4. 对视图的限制 I.5. 对XA事务的限制 J. GNU通用公共许可 K. MySQL FLOSS许可例外 索引 图形清单 14.1. MySQL插件式存储引擎的体系结构 14.2. 存储引擎比较 16.1. MySQL体系结构 表格清单 26.1. 连接属性 26.2. 转换表 26.3. 用于ResultSet.getObject()的MySQL类型和Java类型 26.4. MySQL对Java编码名称的翻译 示例清单 26.1. 从DriverManager获得连接 26.2. 使用java.sql.Statement执行SELECT查询 26.3. 存储程序示例 26.4. 使用Connection.prepareCall() 26.5. 注册输出参数 26.6. 设置CallableStatement输入参数 26.7. 检索结果和输出参数值 26.8. 使用Statement.getGeneratedKeys()检索AUTO_INCREMENT列的值 26.9. 使用SELECT LAST_INSERT_ID()检索AUTO_INCREMENT列的值 26.10. 在可更新的ResultSets中检索AUTO_INCREMENT列的值 26.11. 设置Unix环境下的CLASSPATH 26.12. 与J2EE应用服务器一起使用连接池 26.13. 重试逻辑的事务示例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值