25.6 MySQL 子查询

2024-03-19_184714

1. 子查询

子查询(Subquery): 是SQL查询语句中的一个重要概念, 它允许在一个查询语句(主查询)中嵌套另一个查询语句(子查询).
这意味着一个查询可以作为另一个查询的输入或条件, 子查询可以出现在SQL语句的多个位置, 例如SELECT, FROM, WHERE等子句中.

子查询通常用于以下几种情况:
* 1. WHERE子句中: 子查询可以用作WHERE子句的条件, 以过滤外部查询的结果.
SELECT column1, column2  
FROM table1  
WHERE column1 IN (SELECT columnA FROM table2 WHERE condition);

* 2. FROM子句中: 子查询可以用作FROM子句中的一个表, 通常与别名一起使用.
SELECT alias.column1, alias.column2  
FROM (SELECT columnA AS column1, columnB AS column2 FROM table1 WHERE condition) AS alias;

* 3. SELECT子句中: 子查询可以用作SELECT子句的一部分, 以返回计算结果.
SELECT column1, (SELECT COUNT(*) FROM table2 WHERE table2.columnB = table1.column1) AS count  
FROM table1;

注意:
* 1. 子查询在SQL语句中必须被括在圆括号(), 
     这是因为子查询作为一个独立的查询语句被嵌套在主查询中, 而圆括号用于明确界定子查询的范围.
* 2. 嵌套的子句不需要以分号(;)结尾.
* 3. 一般将来时将子查询放在比较条件的右侧.
* 4. 子查询(内查询)在主查询之前一次执行完成.
* 5. 子查询的结果被主查询(外查询)使用.
* 6. 子查询不能在GROUP BY与LIMIT中使用.
  
子查询可以使查询更加灵活和强, 但它们也可能导致性能问题, 因为每一行外部查询都可能执行一次完整的子查询.
因此, 在编写包含子查询的查询时, 应该考虑到查询的性能, 并尝试优化查询语句. 
子查询和外查询是SQL查询中的两个重要概念:
* 1. 子查询(也称内查询): 是嵌套在其他SQL语句(如SELECT, INSERT, UPDATE或DELETE)中的SELECT语句.
     子查询的结果可以作为外部查询的条件或数据源.
     子查询可以根据其出现的位置和功能进行分类, 例如, 它们可以出现在SELECT语句的后面作为标量子查询,
     或者出现在FROM子句后面作为表子查询.
   

* 2. 外查询(也称主查询): 是包含子查询的外部SQL语句.
     当子查询嵌套在另一个查询中时, 外部的查询语句就是外查询.
     外查询负责处理子查询返回的结果, 并基于这些结果进行进一步的筛选, 排序或其他操作.

在使用子查询和外查询时, 需要注意查询的执行顺序.
一般来说, 子查询会先于外查询执行, 其结果会被外查询使用.
然而, 在某些情况下, 如使用EXISTS子查询时, 外查询会先执行, 然后再执行子查询.  
typora中多行子查手动分行后使用shuift + tab对齐代码好看一些.

1.1 子查询引入

: 员工表中谁的工资比Ellen高?

2024-03-13_030426

-- 现有解决方式:
-- 1. 方式1分布查询:
-- 1.1 先查询Ellen(first_name)的工资:
mysql> SELECT salary FROM employees WHERE first_name = 'Ellen';
+----------+
| salary   |
+----------+
| 11000.00 |
+----------+
1 row in set (0.00 sec)
-- 1.2 在比较谁的工资比Ellen高:
mysql> SELECT first_name, salary FROM employees WHERE salary > 11000 ORDER BY salary;
+------------+----------+
| first_name | salary   |
+------------+----------+
| Lisa       | 11500.00 |
| Nancy      | 12000.00 |
| Alberto    | 12000.00 |
| Shelley    | 12000.00 |
| Michael    | 13000.00 |
| Karen      | 13500.00 |
| John       | 14000.00 |
| Neena      | 17000.00 |
| Lex        | 17000.00 |
| Steven     | 24000.00 |
+------------+----------+
10 rows in set (0.00 sec)

-- 2. 方式2(自连接):
SELECT emp2.first_name, emp2.salary
FROM employees AS `emp1` 
JOIN employees AS `emp2`   -- 笛卡尔积得到107 * 107 = 11449条数据(其中包含Ellen与当前表中所有的行拼接一次的结果).
ON emp1.first_name = 'Ellen' -- 从笛卡尔积中过滤除emp1.last_name = 'Ellen'的数据, 为107条(剩下Abel与所有行的拼接的记录).
AND emp1.salary < emp2.salary;  -- 过滤表二中的薪资大于表一中的薪资的数据.
+------------+----------+
| first_name | salary   |
+------------+----------+
| Steven     | 24000.00 |
| Neena      | 17000.00 |
| Lex        | 17000.00 |
| Nancy      | 12000.00 |
| John       | 14000.00 |
| Karen      | 13500.00 |
| Alberto    | 12000.00 |
| Lisa       | 11500.00 |
| Michael    | 13000.00 |
| Shelley    | 12000.00 |
+------------+----------+
10 rows in set (0.00 sec)
-- 自连接有点难理解, 理解不了就看这个:
SELECT 
emp1.first_name AS `emp1_name`, emp1.salary AS `emp1,_salary`,
emp2.first_name AS `emp2_name`, emp2.salary AS `emp2_salary`
FROM employees AS `emp1` 
JOIN employees AS `emp2`
ON emp1.first_name = 'Ellen' 
ORDER BY emp2_salary;

2024-03-13_031416

问题: 以上方式有好坏之分吗??
解答: 自连接方式好!
题目中可以使用子查询, 也可以使用自连接.
一般情况建议你使用自连接, 因为在许多DBMS的处理过程中, 对于自连接的处理速度要比子查询快得多.
可以这样理解: 子查询实际上是通过未知表进行查询后的条件判断, 
而自连接是通过已知的自身数据表进行条件判断, 因此在大部分DBMS中都对自连接处理进行了优化.

* 在后面的子查询示例中, 使用子查询不一定是最好的解题方式, 这里只是为了学习子查询...

1.2 分步查询与子查询

分步查询和子查询的主要区别在于执行方式: 分步查询是分步骤执行, 而子查询是在一个查询语句中同时执行.
然而, 它们的目的都是将复杂的查询分解为更小的部分, 以提高查询的可读性和可管理性.
: 查询名字为'Jack'的工作的城市.
分步查询方法: 可以通过一张表一张表分步查询.
* 1. 先从员工表中获取获取jack的部门id.
* 2. 拿着部门id去部门表获取地址id.
* 3. 最后通过地址id获取城市的名字.

子查询方式: 最后将三步写成一条sql语句, 前一步操作被后一步操作嵌套.
-- 子查询从内往外的写法:
-- 1. 先从员工表中获取获取jack的部门id:
mysql>
select department_id from employees where first_name = 'jack';
+---------------+
| department_id |
+---------------+
|            80 |
+---------------+
1 row in set (0.00 sec)

-- 2. 拿着部门id去部门表获取地址id(将前面的查询语句作为外查询的过滤依据):
mysql> 
SELECT location_id FROM departments WHERE department_id =
    ( SELECT department_id FROM employees WHERE first_name = 'jack' );
+-------------+
| location_id |
+-------------+
|        2500 |
+-------------+

-- 3. 最后通过地址id获取城市的名字(继续将前面的查询语句作为外查询的过滤依据):
mysql> 
SELECT location_id, city FROM locations WHERE location_id =
    ( SELECT location_id FROM departments WHERE department_id =
        ( SELECT department_id FROM employees WHERE first_name = 'jack' ) );
+-------------+--------+
| location_id | city   |
+-------------+--------+
|        2500 | Oxford |
+-------------+--------+
1 row in set (0.00 sec)

1.3 子查询写法

常见的子查询写法:
* 1. 子查询从内往外的写法: 先写内部查询, 然后将其结果用于外部查询.
     这种写法在逻辑上更直观, 因为它首先定义了内部查询, 然后外部查询基于内部查询的结果来执行.
* 2. 子查询从外往内的写法: 先写外部查询, 然后在外部查询的某个位置(如WHERE子句或SELECT列表中)嵌入内部查询.
     内部查询根据外部查询的需要来定义, 并返回外部查询所需的数据.

通过示例, 展示了如何从外到内和从内到外使用子查询.
: 查询部门员工数超过30号部门员工数的所有部门名称.
-- 子查询从内到外的写法.
-- 1. 先写内查询, id为30的部门员工数量:
mysql> SELECT COUNT(*) FROM employees WHERE department_id = 30;
+----------+
| COUNT(*) |
+----------+
|        6 |
+----------+
1 row in set (0.00 sec)

-- 2. 后写外查询, 查询查询部门员工数超过6的所有部门id:
mysql> SELECT department_id FROM employees GROUP BY department_id HAVING COUNT(department_id) >
( SELECT COUNT(department_id) FROM employees WHERE department_id = 30 );
+---------------+
| department_id |
+---------------+
|            50 |
|            80 |
+---------------+
2 rows in set (0.00 sec)

-- 3. 拿着部门id去部门表中查询部门名称:
mysql> SELECT department_name FROM departments WHERE department_id IN
( SELECT department_id FROM employees GROUP BY department_id HAVING COUNT(department_id) >
( SELECT COUNT(department_id) FROM employees WHERE department_id = 30 ));
+-----------------+
| department_name |
+-----------------+
| Shipping        |
| Sales           |
+-----------------+
2 rows in set (0.00 sec)
-- 子查询从外到内的写法.
-- 1. 从部门表中获取部门名称:
SELECT department_name FROM departments;

-- 2. 需要部门id筛选部门明名称(获取所有部门名称可能有多个部门id这个使用IN):
SELECT department_name FROM departments 
WHERE department_id IN ();

-- 3. 查询所有部门的员工数量:
SELECT department_name FROM departments 
WHERE department_id IN (
    SELECT department_id FROM employees GROUP BY department_id 
);

-- 4. 筛选出部门的员工数量比某个部门员工数量多的部门id:
SELECT department_name FROM departments 
WHERE department_id IN (
    SELECT department_id FROM employees GROUP BY department_id 
    HAVING COUNT(*) > ()
);

-- 5. 获取30号部门的员工个数:
SELECT department_name FROM departments 
WHERE department_id IN (
    SELECT department_id FROM employees GROUP BY department_id 
    HAVING COUNT(*) > (
        SELECT COUNT(*) FROM employees WHERE department_id = 30 )
);
+-----------------+
| department_name |
+-----------------+
| Shipping        |
| Sales           |
+-----------------+
2 rows in set (0.00 sec)
从内往外写可以一步步的去验证, 而从外往内写中间过程无法验证需要一气呵成, 这就需要多加练习.

1.4 子查询的分类

按结果集的行列数, 子查询可以分为:
* 1. 标量子查询(结果集只有一行一列).
* 2. 列子查询(结果集为一列多行).
* 3. 表子查询(结果集一般为多行多列).

image-20240313184306650

按子查询是否被执行多次, 将子查询划分为:
* 1. 不相关子查询(也称非关联子查询或独立子查询): 在执行时与外部查询是独立的.
     首先执行内部查询, 然后将内部查询的结果作为固定条件或数据源传递给外部查询进行执行.
     由于内部查询无法引用外部查询的表或字段, 且其执行与外部查询无关, 因此不相关子查询的执行效率通常较高.
     当查询数量较小时, 非相关子查询往往比相关子查询更为高效.
     然而, 由于其无法动态引用外部查询的数据, 不相关子查询在处理某些复杂的查询需求时可能不如相关子查询灵活.


* 2. 相关子查询(也称关联子查询或嵌套子查询): 在执行时与外部查询紧密相关.
     首先执行外部查询, 然后根据外部查询的每一行数据, 为内部查询提供条件并执行内部查询.
     因此, 相关子查询会针对外部查询的每一行数据重复执行.
     由于内部查询可以引用外部查询的表或字段, 并根据外部查询的结果动态地改变条件,
     这使得相关子查询在处理某些复杂的查询需求时非常有用.
     然而, 由于需要重复执行内部查询, 当查询数量较大时, 相关子查询的效率可能会受到影响.
     

* 简单来说: 
  子查询从数据表中查询了数据结果, 如果这个数据结果只执行一次
  然后这个数据结果作为主查询的条件进行执行, 那么这样的子查询叫做不相关子查询.

  如果子查询需要执行多次, 即采用循环的方式, 先从外部查询开始,每次都传入子查询进行查询,
  然后再将结果反馈给外部, 这种嵌套的执行方式就称为相关子查询.

  它们在执行顺序, 引用外部查询的方式以及嵌套层级等方面存在显著的差异.

2. 单行子查询

单行子查询(Single-Row Subquery): 是SQL查询中的一种特定类型, 它返回的结果集仅包含一行数据.
这种子查询通常用于在外部查询中作为条件或值来引用.
当你知道子查询将只返回一行数据, 并且你需要这行数据来完成外部查询时, 单行子查询是非常有用的.

单行子查询通常用在SELECT, INSERT, UPDATE或DELETE语句中, 作为WHERE子句或SET子句的一部分.
由于它们只返回一行数据, 所以可以使用比较运算符来比较子查询的结果与外部查询的列值.

2.1 单行比较操作符

操作符描述示例
=等于WHERE column1 = value
>大于WHERE column1 > value
>=大于或等于WHERE column1 >= value
<小于WHERE column1 < value
<=小于或等于WHERE column1 <= value
<> 或 !=不等于WHERE column1 <> valueWHERE column1 != value
在这个表格中, column1代表表中的某个列名, value是与该列进行比较的值.
单行比较操作符通常用于WHERE子句中, 来过滤满足特定条件的行.

注意: 单行比较操作符只适用于单行子查询.

2.2 单行子查询示例

-- 1.  查询工资大于149号员工工资的员工信息(名字, 薪资):
-- 1.1 获取149员工的薪资:
mysql> SELECT salary FROM employees WHERE employee_id = 149;
+----------+
| salary   |
+----------+
| 10500.00 |
+----------+
1 row in set (0.00 sec)

-- 1.2 查询工资大于10500的员工信息(名字, 薪资):
mysql> SELECT first_name, salary FROM employees WHERE salary > (
    SELECT salary FROM employees WHERE employee_id = 149 );
+------------+----------+
| first_name | salary   |
+------------+----------+
| Steven     | 24000.00 |
| Neena      | 17000.00 |
| Lex        | 17000.00 |
| Nancy      | 12000.00 |
| Den        | 11000.00 |
| John       | 14000.00 |
| Karen      | 13500.00 |
| Alberto    | 12000.00 |
| Gerald     | 11000.00 |
| Lisa       | 11500.00 |
| Ellen      | 11000.00 |
| Michael    | 13000.00 |
| Shelley    | 12000.00 |
+------------+----------+
13 rows in set (0.00 sec)
-- 2. 返回岗位(job_id)与141号员工相同, salary比143号员工多的员工信息(名字, 岗位, 工资):
-- 2.1 查询141号员工的岗位:
mysql> SELECT job_id FROM employees WHERE employee_id = 141;
+----------+
| job_id   |
+----------+
| ST_CLERK |
+----------+
1 row in set (0.00 sec)

-- 2.2 查询143号员工的薪资:
mysql> SELECT salary FROM employees WHERE employee_id = 143;
+---------+
| salary  |
+---------+
| 2600.00 |
+---------+
1 row in set (0.00 sec)

-- 2.3 查询ST_CLERK岗位的员工工资比2600多的员工信息,
-- (通常情况下, 不需要排除141号员工的信息, 除非有特定的业务需求指明要排除他):
mysql> SELECT first_name, job_id, salary FROM employees 
WHERE job_id = (SELECT job_id FROM employees WHERE employee_id = 141)
AND salary > (SELECT salary FROM employees WHERE employee_id = 143)
ORDER BY salary;
+------------+----------+---------+
| first_name | job_id   | salary  |
+------------+----------+---------+
| Irene      | ST_CLERK | 2700.00 |
| John       | ST_CLERK | 2700.00 |
| Mozhe      | ST_CLERK | 2800.00 |
| Michael    | ST_CLERK | 2900.00 |
| Curtis     | ST_CLERK | 3100.00 |
| Julia      | ST_CLERK | 3200.00 |
| Stephen    | ST_CLERK | 3200.00 |
| Laura      | ST_CLERK | 3300.00 |
| Jason      | ST_CLERK | 3300.00 |
| Trenna     | ST_CLERK | 3500.00 |
| Renske     | ST_CLERK | 3600.00 |
+------------+----------+---------+
11 rows in set (0.00 sec))
-- 3. 返回公司工资最少的员工的信息(名字, 岗位, 薪资):
-- 3.1 查询最低工资:
mysql> SELECT MIN(salary) FROM employees;
+-------------+
| MIN(salary) |
+-------------+
|     2100.00 |
+-------------+
1 row in set (0.00 sec)

-- 3.2 查询工资为2100的员工信息:
mysql> SELECT first_name, job_id, salary FROM employees
WHERE salary = ( SELECT MIN(salary) FROM employees );
+------------+----------+---------+
| first_name | job_id   | salary  |
+------------+----------+---------+
| TJ         | ST_CLERK | 2100.00 |
+------------+----------+---------+
1 row in set (0.00 sec)
-- 4. 查询与141号或174号员工的manager_id和department_id相同的其他员工的员工信息(员工id, 管理者id, 部门id):
-- 4.1.1 查询141, 174号员工的部门id:
mysql> SELECT department_id FROM employees WHERE employee_id IN (141, 174);
+---------------+
| department_id |
+---------------+
|            50 |
|            80 |
+---------------+
2 rows in set (0.00 sec)

-- 4.1.2 查询141, 174号员工的管理者id:
mysql> SELECT manager_id FROM employees WHERE employee_id IN (141, 174);
+------------+
| manager_id |
+------------+
|        124 |
|        149 |
+------------+
2 rows in set (0.00 sec)

-- 4.1.3 查询部门id为50和80, 管理者id为124和149的员工信息:
mysql> SELECT manager_id, manager_id, department_id FROM employees
WHERE department_id IN (SELECT department_id FROM employees WHERE employee_id IN (141, 174))
AND manager_id IN (SELECT manager_id FROM employees WHERE employee_id IN (141, 174));
+------------+------------+---------------+
| manager_id | manager_id | department_id |
+------------+------------+---------------+
|        124 |        124 |            50 |
|        124 |        124 |            50 |
|        124 |        124 |            50 |
|        124 |        124 |            50 |
|        124 |        124 |            50 |
|        124 |        124 |            50 |
|        124 |        124 |            50 |
|        124 |        124 |            50 |
|        149 |        149 |            80 |
|        149 |        149 |            80 |
|        149 |        149 |            80 |
|        149 |        149 |            80 |
|        149 |        149 |            80 |
+------------+------------+---------------+
13 rows in set (0.00 sec)

-- 4.1.4 其他二字表示了排除141, 174的员工信息.
mysql> SELECT employee_id, manager_id, department_id FROM employees
WHERE department_id IN (SELECT department_id FROM employees WHERE employee_id IN (141, 174))
AND manager_id IN (SELECT manager_id FROM employees WHERE employee_id IN (141, 174))
AND employee_id NOT IN (141, 174);
+-------------+------------+---------------+
| employee_id | manager_id | department_id |
+-------------+------------+---------------+
|         142 |        124 |            50 |
|         143 |        124 |            50 |
|         144 |        124 |            50 |
|         196 |        124 |            50 |
|         197 |        124 |            50 |
|         198 |        124 |            50 |
|         199 |        124 |            50 |
|         175 |        149 |            80 |
|         176 |        149 |            80 |
|         177 |        149 |            80 |
|         179 |        149 |            80 |
+-------------+------------+---------------+
11 rows in set (0.00 sec)


-- 成对匹配:
-- 4.2.1 查询141, 174号员工的部门id, 管理者id:
mysql> SELECT department_id, manager_id FROM employees WHERE employee_id IN (141, 174);
+---------------+------------+
| department_id | manager_id |
+---------------+------------+
|            50 |        124 |
|            80 |        149 |
+---------------+------------+
2 rows in set (0.00 sec)

-- 4.2.2 查询部门id为50和80, 管理者id为124和149的员工信息:
mysql> SELECT employee_id, manager_id, department_id FROM employees
WHERE (department_id, manager_id) IN (
SELECT department_id, manager_id FROM employees WHERE employee_id IN (141, 174 ));
+-------------+------------+---------------+
| employee_id | manager_id | department_id |
+-------------+------------+---------------+
|         141 |        124 |            50 |
|         142 |        124 |            50 |
|         143 |        124 |            50 |
|         144 |        124 |            50 |
|         196 |        124 |            50 |
|         197 |        124 |            50 |
|         198 |        124 |            50 |
|         199 |        124 |            50 |
|         174 |        149 |            80 |
|         175 |        149 |            80 |
|         176 |        149 |            80 |
|         177 |        149 |            80 |
|         179 |        149 |            80 |
+-------------+------------+---------------+
13 rows in set (0.00 sec)

-- 4.2.3 排除141, 174的员工信息:
mysql> SELECT employee_id, manager_id, department_id FROM employees
WHERE (department_id, manager_id) IN (
SELECT department_id, manager_id FROM employees WHERE employee_id IN (141, 174 ))
AND employee_id NOT IN (141, 174);
+-------------+------------+---------------+
| employee_id | manager_id | department_id |
+-------------+------------+---------------+
|         142 |        124 |            50 |
|         143 |        124 |            50 |
|         144 |        124 |            50 |
|         196 |        124 |            50 |
|         197 |        124 |            50 |
|         198 |        124 |            50 |
|         199 |        124 |            50 |
|         175 |        149 |            80 |
|         176 |        149 |            80 |
|         177 |        149 |            80 |
|         179 |        149 |            80 |
+-------------+------------+---------------+
11 rows in set (0.00 sec)

2.3 HAVING中的子查询

-- 5. 查询部门最低工资大于50号部门最低工资的部门id和其最低工资:
-- 查询'部门最低工资'大于'50号部门最低工资'的'部门id'和其'最低工资':

-- 5.1 查询每个部门最低工资:
mysql> SELECT department_id, MIN(salary) FROM employees GROUP BY department_id;
+---------------+-------------+
| department_id | MIN(salary) |
+---------------+-------------+
|          NULL |     7000.00 |
|            10 |     4400.00 |
|            20 |     6000.00 |
|            30 |     2500.00 |
|            40 |     6500.00 |
|            50 |     2100.00 |
|            60 |     4200.00 |
|            70 |    10000.00 |
|            80 |     6100.00 |
|            90 |    17000.00 |
|           100 |     6900.00 |
|           110 |     8300.00 |
+---------------+-------------+
12 rows in set (0.00 sec)


-- 5.2 查询50号部门的最低工资:
mysql> SELECT MIN(salary) FROM employees WHERE department_id = 50;
+-------------+
| MIN(salary) |
+-------------+
|     2100.00 |
+-------------+
1 row in set (0.00 sec)

-- 5.3 过滤部门最低工资大于2100的信息:
mysql> SELECT department_id, MIN(salary) AS `min_salary` FROM employees GROUP BY department_id 
HAVING min_salary > ( SELECT MIN(salary) FROM employees WHERE department_id = 50 ) 
ORDER BY min_salary;
+---------------+------------+
| department_id | min_salary |
+---------------+------------+
|            30 |    2500.00 |
|            60 |    4200.00 |
|            10 |    4400.00 |
|            20 |    6000.00 |
|            80 |    6100.00 |
|            40 |    6500.00 |
|           100 |    6900.00 |
|          NULL |    7000.00 |
|           110 |    8300.00 |
|            70 |   10000.00 |
|            90 |   17000.00 |
+---------------+------------+
11 rows in set (0.00 sec)

2.4 CASE中的子查询

-- 6. 显式员工的信息(员工id, 名字, 地址).
-- 其中, 若'员工的部门id'与'地址id为1800的department_id'相同, 则地址为'Canada', 其余则为'USA'.

-- 6.1 查询地址id为1800的信息(部门id):
mysql> SELECT department_id FROM departments WHERE location_id = 1800;
+---------------+
| department_id |
+---------------+
|            20 |
+---------------+
1 row in set (0.00 sec)

-- 6.2 部门id为20则地址显示为Canada, 否则为'USA';
SELECT employee_id, first_name,
CASE department_id  -- 条件表示
     WHEN (SELECT department_id FROM departments WHERE location_id = 1800) THEN 'Canada'
     ELSE 'USA'
END 'location'
FROM employees;
+-------------+-------------+----------+
| employee_id | first_name  | location |
+-------------+-------------+----------+
|         ... | ...         | ...      | -- 省略
|         101 | Neena       | USA      |
|         102 | Lex         | USA      |
|         199 | Douglas     | USA      |
|         200 | Jennifer    | USA      |
|         201 | Michael     | Canada   |
|         202 | Pat         | Canada   |
|         203 | Susan       | USA      |
|         204 | Hermann     | USA      |
|         205 | Shelley     | USA      |
|         206 | William     | USA      |
+-------------+-------------+----------+
107 rows in set (0.00 sec)

2.5 子查询中的空值与空行

子查询中的空值与空行问题是在数据库查询中经常遇到的挑战.
它们可能导致查询结果不准确或返回不期望的结果集.

下面将分别讨论这两个问题及其处理方法:
* 1. 子查询中的空值问题.
     空值(NULL)在数据库中表示缺失或未知的数据. 在子查询中, 空值可能导致以下问题:
     1. 比较操作失败: 当使用等于(=)或不等于(<>)操作符与NULL进行比较时, 结果总是未知的(即NULL),
         因为无法确定NULL与任何值的比较结果.

     2. 聚合函数的影响: 某些聚合函数(如COUNT, SUM等)在处理NULL值时会有特定的行为.
         例如, COUNT(字段)函数会忽略NULL值, 而SUM函数则会将NULL视为0.

     3. 连接操作的问题: 在使用子查询进行连接操作时, 如果子查询返回NULL值, 可能会影响连接的结果.
         特别是当使用内连接(INNER JOIN), 如果连接条件中包含NULL值, 则不会返回任何匹配的行.

     为了处理子查询中的空值问题, 可以采取以下策略:
     1. 使用IS NULL或IS NOT NULL来检查空值, 而不是使用等于或不等于操作符.
     2. 在子查询中使用COALESCE函数或其他空值处理函数来替换或转换空值.
     3. 确保主查询和子查询中的逻辑能够正确处理NULL值, 避免因为空值而导致查询失败或返回不准确的结果.
     
* 2. 子查询返回空行的问题.
     当子查询没有返回任何行(即返回空行), 这通常意味着子查询的条件没有匹配到任何记录.
     这可能导致主查询不返回任何结果或返回不完整的结果集.

     处理子查询返回空行的问题的方法取决于具体的查询需求和场景:
     1. 检查子查询条件: 首先, 确保子查询的条件是正确的, 并且确实应该返回数据.
        如果条件太严格或存在逻辑错误, 可能会导致子查询返回空行.
     2. 使用LEFT JOIN或RIGHT JOIN: 如果子查询用于连接操作, 并且返回空行导致主查询结果不完整.
        可以考虑使用LEFT JOIN或RIGHT JOIN来替代子查询. 这样即使子查询没有返回匹配的行, 主查询也可以返回部分结果.
     3. 处理NULL值: 如果子查询返回空行是因为某些字段的值为NULL, 并且这些NULL值影响了查询结果,
        可以在子查询或主查询中使用相应的空值处理策略.

     4. 使用EXISTS或NOT EXISTS: 如果只需要检查子查询是否存在结果而不关心具体的返回值, 可以使用EXISTS或NOT EXISTS操作符.
        这些操作符会在子查询返回任何行时返回真或假, 而不受返回行数的影响.

综上所述, 处理子查询中的空值与空行问题需要仔细分析查询逻辑和数据结构, 并采取适当的策略来确保查询结果的准确性和可靠性.
通过合理的空值处理和逻辑设计, 可以避免这些问题对查询结果的影响.
-- 下面这段SQL代码的功能是从employees表中选择与名为'Haas'的员工具有相同job_id的所有员工的first_name和job_id.
mysql> SELECT first_name, job_id
FROM  employees
WHERE job_id =
       ( SELECT job_id
         FROM  employees
         WHERE first_name = 'Haas' );
Empty set (0.00 sec) -- 没有返回任何结果.

-- 代码的执行流程: 首先执行子查询(内部查询), 后执行外部查询.
-- 所有先检查子查询是否返回有效的数据:
mysql> SELECT job_id FROM  employees WHERE first_name = 'Haas';
Empty set (0.00 sec) -- 没有返回任何结果.
-- 因为子查询没有返回有效的数据, 导致主查询没有返回任何结果.

2.6 非法使单行比较操作符

在MySQL中, 非法使用单行比较操作符会导致错误的行为.
-- 错误示例: 查询每个部门的最低工资的员工信息(部门id, 姓名)
mysql> SELECT employee_id, first_name
FROM  employees
WHERE salary =
        ( SELECT  MIN(salary)
         FROM   employees
         GROUP BY department_id );
ERROR 1242 (21000): Subquery returns more than 1 row
-- 错误 1242 (21000): 子查询返回多于一行

-- 查看子查询返回的结果(是一个多行子查询):
mysql> SELECT MIN(salary) FROM employees GROUP BY department_id;
+-------------+
| MIN(salary) |
+-------------+
|     7000.00 |
|     4400.00 |
|     6000.00 |
|     2500.00 |
|     6500.00 |
|     2100.00 |
|     4200.00 |
|    10000.00 |
|     6100.00 |
|    17000.00 |
|     6900.00 |
|     8300.00 |
+-------------+
12 rows in set (0.00 sec)
错误的原因: 由于子查询返回了多行结果, 而主查询的WHERE子句期望子查询返回一个单一值来进行比较.
单行比较操作符只适用于单行子查询, 不能被多行子查询使用.

3. 表子查询与派生表

表子查询(也称为多行子查询或多列子查询): 是指子查询返回的结果集是一个包含多行多列的表数据.
这种子查询的结果相当于一个表, 可以直接当作一个表来使用.
在SQL查询中, 表子查询通常用在主查询的FROM子句中, 作为一个'数据源'供主查询使用.
派生表: 又称为子查询表或虚拟表, 是SQL查询中的一个临时结果集.
它通过子查询创建, 并在查询执行期间存在, 一旦查询完成, 派生表就会被销毁.
派生表允许你将复杂的查询逻辑封装在子查询中, 从而使主查询更加简洁和清晰.
-- 派生表格式:
SELECT column1, column2, ...
FROM (
    -- 子查询语句,生成派生表
    SELECT columnA, columnB, ...  -- 别名就是虚拟表的列名
    FROM your_table
    WHERE conditions
    GROUP BY columnC
    HAVING conditions
    -- 可以包含其他SQL子句, 如ORDER BY, LIMIT等
) AS derived_table_name  -- MySQL数据库管理系统明确要求为每个派生表提供别名
WHERE conditions
使用派生表的注意事项:
* 1. 性能考虑: 虽然派生表可以简化查询逻辑, 但过度使用或在不必要的情况下使用可能会导致性能下降.
     因此, 在使用派生表之前, 应评估其对查询性能的影响, 并根据实际情况进行选择.
* 2. 可读性: 复杂的派生表结构可能会降低查询的可读性.
     为了保持代码清晰和易于维护, 建议尽量简化派生表的逻辑, 并避免过度嵌套.
* 3. 列名唯一性: 派生表中的列名必须是唯一的, 不能有重复的列名.
     确保为每个列指定一个明确的名称, 以避免混淆和错误.
* 4. 避免在派生表中使用ORDER BY: 除非在派生表中使用TOP关键字来限制返回的记录数,
     否则通常不允许在派生表的定义中使用ORDER BY子句进行排序.
     这是因为排序操作通常是在查询的最终结果集上进行的, 而不是在派生表的中间结果集上.
* 5. 派生表在SQL查询中一定要有别名.
     这是因为派生表是通过子查询生成的临时结果集, 而在SQL查询中, 每个表(包括派生表)都需要一个唯一的标识符来引用其列和数据.
     这个唯一的标识符就是别名.
     MySQL数据库管理系统明确要求为每个派生表提供别名. 如果在查询中没有为派生表指定别名,
     MySQL会报错并提示'Every derived table must have its own alias'(每个派生表必须具有自己的别名).
     因此, 为了避免错误并提高查询的清晰度, 应该始终为派生表指定别名.
-- 查询平均工资超过10000的部门(部门id, 平均工资):
-- 1.1 查询各部门的平均工资:
mysql> SELECT department_id, AVG(salary) AS `avg_salary` FROM employees GROUP BY department_id
ORDER BY avg_salary;
+---------------+--------------+
| department_id | avg_salary   |
+---------------+--------------+
|            50 |  3475.555556 |
|            30 |  4150.000000 |
|            10 |  4400.000000 |
|            60 |  5760.000000 |
|            40 |  6500.000000 |
|          NULL |  7000.000000 |
|           100 |  8600.000000 |
|            80 |  8955.882353 |
|            20 |  9500.000000 |
|            70 | 10000.000000 |
|           110 | 10150.000000 |
|            90 | 19333.333333 |
+---------------+--------------+
12 rows in set (0.00 sec)


-- 1.2 将查询语句的结果设置为派生表:
mysql> SELECT * FROM (
    SELECT department_id, AVG(salary) AS `avg_salary` FROM employees GROUP BY department_id
    ORDER BY avg_salary  -- 排序可以省略 
) AS `avg_salary_table`;  -- 设置为虚拟表
+---------------+--------------+
| department_id | avg_salary   |
+---------------+--------------+
|            50 |  3475.555556 |
|            30 |  4150.000000 |
|            10 |  4400.000000 |
|            60 |  5760.000000 |
|            40 |  6500.000000 |
|          NULL |  7000.000000 |
|           100 |  8600.000000 |
|            80 |  8955.882353 |
|            20 |  9500.000000 |
|            70 | 10000.000000 |
|           110 | 10150.000000 |
|            90 | 19333.333333 |
+---------------+--------------+
12 rows in set (0.00 sec)

-- 查询平均工资大于10000的部门:
SELECT * FROM (
    SELECT department_id, AVG(salary) AS `avg_salary` FROM employees GROUP BY department_id
ORDER BY avg_salary  
) AS `avg_salary_table`
WHERE avg_salary > 10000;  -- 展示的别名就是虚拟表的列名.
+---------------+--------------+
| department_id | avg_salary   |
+---------------+--------------+
|           110 | 10150.000000 |
|            90 | 19333.333333 |
+---------------+--------------+
2 rows in set (0.00 sec)

4. 多行子查询

多行子查询(Multi-Row Subquery): 是SQL查询中的一种特定类型, 它指的是子查询返回多行结果的查询.
子查询是嵌套在主查询中的查询, 可以作为主查询的一部分, 用于返回需要的数据结果.
多行子查询在数据库查询中非常有用, 因为它允许我们在一个查询中结合多个条件和数据集.

4.1 多行子查询操作符

操作符描述
IN用于判断某个值是否存在于子查询返回的结果集中.
ANY或SOME与子查询返回的每一个值进行比较, 只需匹配任一结果.
ALL与子查询返回的所有值进行比较, 必须匹配所有结果.
注意: ANY和ALL操作符必须与单行比较运算符(=, <, >)结合使用, 并且子查询必须返回多行数据.
此外, 当使用这些多行子查询操作符时, 应确保子查询的性能优化, 以避免对数据库性能产生负面影响.
IN操作符: 用于判断某个值是否存在于子查询返回的结果集中.
如果子查询返回多行数据, 并且主查询中的某个值与子查询返回的任何一行数据匹配, 则IN操作符返回TRUE.
* 当你不确定子查询返回的数据条目数时, 使用IN通常比使用等号(=)更安全.
  等号只能用于比较单个值, 而IN允许子查询返回多个值(包含单个值的情况).

4.2 多行子查询示例

-- 1. 查找与每个部门最低工资相同的员工信息(员工id, 姓名, 薪资):
-- 1.1 查询每个部门的最新工资:
mysql> SELECT MIN(salary) FROM employees GROUP BY department_id;
+-------------+
| MIN(salary) |
+-------------+
|     7000.00 |
|         ... | -- 省略
|     6100.00 |
|    17000.00 |
|     6900.00 |
|     8300.00 |
+-------------+
12 rows in set (0.00 sec)

-- 1.2 查询工资为(x1, x2)的员工信息:
SELECT employee_id, first_name, salary FROM employees  
WHERE salary IN ( SELECT MIN(salary) FROM employees GROUP BY department_id );
+-------------+------------+----------+
| employee_id | first_name | salary   |
+-------------+------------+----------+
|         101 | Neena      | 17000.00 |
|         102 | Lex        | 17000.00 |
|         104 | Bruce      |  6000.00 |
|         ... | ...        |      ... | -- 省略
|         203 | Susan      |  6500.00 |
|         204 | Hermann    | 10000.00 |
|         206 | William    |  8300.00 |
+-------------+------------+----------+
26 rows in set (0.00 sec)
ANY操作符: 用于与子查询返回的每一个值进行比较.
如果主查询中的某个值与子查询返回的任何一个值满足比较条件(如大于, 小于, 等于等), 则ANY操作符返回TRUE.
-- 2. 查找工资比20号部门任意员工高的员工信息(员工id, 姓名, 薪资):
-- 2.1 查询20号部门员工的工资:
mysql> SELECT salary FROM employees WHERE department_id = 20;
+----------+
| salary   |
+----------+
| 13000.00 |
|  6000.00 |  -- 此题中, 主查询基于'最低'标准来比较.
+----------+
2 rows in set (0.01 sec)

-- 2.2 查询工资比(x1, x2中最低值)高的员工信息:
mysql> SELECT employee_id, first_name, salary FROM employees  
WHERE salary > ANY ( SELECT salary FROM employees WHERE department_id = 20 )
ORDER BY salary;
+-------------+-------------+----------+
| employee_id | first_name  | salary   |
+-------------+-------------+----------+
|         173 | Sundita     |  6100.00 |
|         179 | Charles     |  6200.00 |
|         ... | ...         |      ... | -- 省略
|         145 | John        | 14000.00 |
|         101 | Neena       | 17000.00 |
|         102 | Lex         | 17000.00 |
|         100 | Steven      | 24000.00 |
+-------------+-------------+----------+
55 rows in set (0.00 sec)
ALL操作符: 用于与子查询返回的所有值进行比较.
只有当主查询中的某个值与子查询返回的所有值都满足比较条件时, ALL操作符才返回TRUE.
-- 3. 查找工资低于所有IT_PROG部门员工工资的员工信息(员工id, 姓名, 薪资).
-- 3.1 查询IT_PROG岗位的员工工资:
mysql> SELECT salary FROM employees WHERE job_id = 'IT_PROG';
+---------+
| salary  |
+---------+
| 9000.00 |
| 6000.00 |
| 4800.00 |
| 4800.00 |
| 4200.00 |  -- 此题中, 基于此数据为'最低'标准比较.
+---------+
5 rows in set (0.01 sec)

-- 3.2 查询工资比(x1, x2, ..., 中最低值)低的员工信息:
 SELECT employee_id, first_name, salary FROM employees 
 WHERE salary < ALL ( SELECT salary FROM employees WHERE job_id = 'IT_PROG' ) 
 ORDER BY salary;
+-------------+------------+---------+
| employee_id | first_name | salary  |
+-------------+------------+---------+
|         132 | TJ         | 2100.00 |
|         128 | Steven     | 2200.00 |
|         ... | ...        |     ... | -- 省略
|         137 | Renske     | 3600.00 |
|         189 | Jennifer   | 3600.00 |
|         188 | Kelly      | 3800.00 |
|         193 | Britney    | 3900.00 |
|         192 | Sarah      | 4000.00 |
|         185 | Alexis     | 4100.00 |
+-------------+------------+---------+
44 rows in set (0.00 sec)
-- 4. 返回那些在其他岗位(即非'IT_PROG'岗位)工作且其工资低于'IT_PROG'岗位任一员工工资的员工信息(工号, 姓名, 岗位以及薪资):
-- 4.1 查询IT_PROG岗位的薪资:
mysql> SELECT salary FROM employees WHERE job_id = 'IT_PROG';
+---------+
| salary  |
+---------+
| 9000.00 |  -- 此题中, 基于此数据为'最高'标准比较.
| 6000.00 |
| 4800.00 |
| 4800.00 |
| 4200.00 |  
+---------+
5 rows in set (0.00 sec)

-- 4.2 查询工资
SELECT employee_id, first_name, job_id, salary FROM employees
WHERE job_id != 'IT_PROG'
AND salary < any (SELECT salary FROM employees WHERE job_id = 'IT_PROG')
ORDER BY salary;
+-------------+-------------+------------+---------+
| employee_id | first_name  | job_id     | salary  |
+-------------+-------------+------------+---------+
|         132 | TJ          | ST_CLERK   | 2100.00 |
|         128 | Steven      | ST_CLERK   | 2200.00 |
|         ... | ...         | ...        |     ... |  -- 省略
|         159 | Lindsey     | SA_REP     | 8000.00 |
|         153 | Christopher | SA_REP     | 8000.00 |
|         110 | John        | FI_ACCOUNT | 8200.00 |
|         121 | Adam        | ST_MAN     | 8200.00 |
|         206 | William     | AC_ACCOUNT | 8300.00 |
|         177 | Jack        | SA_REP     | 8400.00 |
|         176 | Jonathon    | SA_REP     | 8600.00 |
|         175 | Alyssa      | SA_REP     | 8800.00 |
+-------------+-------------+------------+---------+
76 rows in set (0.00 sec)
-- 5. 查询平均工资最低的部门信息(部门id, 部门平均工资):
-- 方式1:
-- 5.1.1 查平均所有部门的平均工资:
mysql> SELECT AVG(salary) FROM employees GROUP BY department_id;
+--------------+
| AVG(salary)  |
+--------------+
|  7000.000000 |
|  4400.000000 |
|  9500.000000 |
|  4150.000000 |
|  6500.000000 |
|  3475.555556 |  
|  5760.000000 |
| 10000.000000 |
|  8955.882353 |
| 19333.333333 |
|  8600.000000 |
| 10150.000000 |
+--------------+
12 rows in set (0.00 sec)

-- 5.1.2 查询最低的平均工资:
mysql> SELECT MIN(avg_salary) FROM (  -- 从虚拟表中查询数据
    SELECT AVG(salary) AS `avg_salary` -- 虚拟表的展示的列名
    FROM employees GROUP BY department_id
) AS `avg_salary_table`;      -- 虚拟表别名(必须)
+-----------------+
| MIN(avg_salary) |
+-----------------+
|     3475.555556 |
+-----------------+
1 row in set (0.00 sec)

-- 5.1.3 查询工资为3475的部门信息:
mysql> SELECT department_id, AVG(salary) AS `avg_salary` FROM employees GROUP BY department_id 
HAVING avg_salary = (
SELECT MIN(avg_salary) FROM (  
        SELECT AVG(salary) AS `avg_salary` FROM employees GROUP BY department_id
) AS `avg_salary_table`);
+---------------+-------------+
| department_id | avg_salary  |
+---------------+-------------+
|            50 | 3475.555556 |
+---------------+-------------+
1 row in set (0.01 sec)

-- 方式2:
-- 5.2.1 查询平均所有部门的平均工资:
mysql> SELECT AVG(salary) FROM employees GROUP BY department_id;
+--------------+
| AVG(salary)  |
+--------------+
|  7000.000000 |
|  4400.000000 |
|  9500.000000 |
|  4150.000000 |
|  6500.000000 |
|  3475.555556 |  -- 最低标准, 使用( <= ALL) 比较, 可以理解为为小于或等于列表最低值.
|  5760.000000 |
| 10000.000000 |
|  8955.882353 |
| 19333.333333 |
|  8600.000000 |
| 10150.000000 |
+--------------+
12 rows in set (0.00 sec)

-- 5.2.2 查询平均小于或等于3475的:
SELECT department_id, AVG(salary) AS `avg_salary` FROM employees
GROUP BY department_id HAVING avg_salary <= ALL (
    SELECT AVG(salary) FROM employees GROUP BY department_id);
+---------------+-------------+
| department_id | avg_salary  |
+---------------+-------------+
|            50 | 3475.555556 |
+---------------+-------------+
1 row in set (0.00 sec)

2024-03-15_191929

4.3 多行子查询空值问题

多行子查询空值问题主要出现在使用NOT IN操作符时:
如果子查询返回的结果中包含NULL值, 那么整个NOT IN表达式的结果将会是空值(NULL), 而不是预期的非匹配结果.
这是因为NULL在SQL中代表未知或缺失的值, 与任何值的比较(包括自身)结果都是未知(NULL).

解决方式: 
* 1. 使用IS NULL和IS NOT NULL排除子查询中的NULL值.
* 2. 使用LEFT JOIN代替NOT IN, 并通过检查连接键是否为NULL来找到非匹配的行.
* 3. 使用EXISTS或ANY代替NOT IN避免NULL值的问题。
-- 示例: 查询没有下级员工的员工信息:
-- 1. 查询员工的上级id:
mysql> SELECT manager_id FROM employees GROUP BY manager_id;
+------------+
| manager_id |
+------------+
|       NULL |
|        100 |
|        ... |
|        147 |
|        148 |
|        149 |
|        201 |
|        205 |
+------------+
19 rows in set (0.00 sec) -- 不是管理者的有: 107 - 19 = 88, 不算NULL则是89. 

-- 2. 查询不是管理者的员工信息(员工id不在'管理者id'范围内):
SELECT first_name FROM employees
WHERE employee_id NOT IN ( SELECT manager_id FROM employees GROUP BY manager_id);
Empty set (0.01 sec)

-- 3. 排除子查询中的NULL值:
SELECT first_name FROM employees
WHERE employee_id NOT IN (
    SELECT manager_id FROM employees
    WHERE manager_id IS NOT NULL
    GROUP BY manager_id );
+-------------+
| first_name  |
+-------------+
| Bruce       |
| David       |
| Valli       |
|   ...       |
| Douglas     |
| Jennifer    |
| Pat         |
| Susan       |
| Hermann     |
| William     |
+-------------+
89 rows in set (0.00 sec)

-- 或:
SELECT first_name
FROM employees
WHERE employee_id NOT IN (
    SELECT manager_id FROM employees
    WHERE manager_id IS NOT NULL );

5. 相关子查询

5.1 相关子查询执行流程

关联子查询是SQL中一种特殊的子查询类型, 它的执行依赖于外部查询的结果.
这是因为子查询中引用了外部查询的列或表, 并且它们之间通过某种条件进行了关联.

当执行一个包含关联子查询的SQL语句时, 数据库管理系统会按照以下步骤进行:
* 1. 外部查询初始化: 首先, 外部查询开始执行, 并准备获取数据.

* 2. 逐行处理: 对于外部查询的每一行, 都会执行一次关联子查询.
     这意味着, 如果外部查询返回10行数据, 那么关联子查询将至少执行10.

* 3. 子查询执行: 在每次执行关联子查询时, 它都会引用当前外部查询行的相关列值, 并根据这些值来过滤或计算子查询的结果.

* 4. 结果返回: 一旦子查询执行完毕并得出结果, 这个结果就会用于外部查询的当前行, 以确定该行是否满足外部查询的条件.

* 5. 继续处理: 然后, 外部查询会移到下一行, 并重复上述步骤, 直到所有行都被处理完毕.

相关子查询是与外部查询的每一行都相关联的, 它会根据外部查询的每一行数据动态地执行子查询.
对于外部查询表中的每一行, 都会执行一次子查询, 以基于该行的数据来获取相关信息或计算结果.
因此, 外查询表中有多少条数据, 相关子查询就会执行多少次, 如果外部查询表中有N条数据, 那么相关子查询就会执行N次.

这种执行方式虽然可以灵活地处理每一行数据的特定需求, 但在处理大量数据时可能会导致性能问题.
因此, 在编写涉及相关子查询的SQL语句时, 需要仔细考虑查询的性能, 并考虑是否可以通过其他方式(如JOIN操作)来优化查询.

image-20240315203419372

常见的相关子查询的语法格式示例:
SELECT column1, column2, ...  
FROM table1  
WHERE columnX operator (  
    SELECT columnY  
    FROM table2  
    WHERE table1.common_column = table2.common_column  --  子查询中的关联条件, 它连接了外部查询和子查询. 
);

子查询中的table1.common_column引用了外部查询的表table1的列, 这使得子查询的执行依赖于外部查询的当前行.

5.2 相关子查询示例

-- 1. 查询员工人数超过10人的部门信息(部门id, 部门名称):
SELECT department_id, department_name  
FROM departments as `dep`
WHERE (  
    SELECT COUNT(*)  
    FROM employees AS `emp`  
    WHERE emp.department_id = dep.department_id  -- 关联条件
) > 10;
+---------------+-----------------+
| department_id | department_name |
+---------------+-----------------+
|            50 | Shipping        |
|            80 | Sales           |
+---------------+-----------------+
2 rows in set (0.00 sec)
执行步骤说明:
数据库管理系统会遍历departments表的每一行.
对于每一行, 它都会执行内部的SELECT COUNT(*)子查询, 来计算当前部门在employees表中的员工数量.
然后, 它会检查这个计数是否大于10.
如果是, 那么它就会将当前部门的department_id和department_name添加到结果集中.
这个过程会一直持续到departments表的所有行都被处理完毕.
最后, 数据库管理系统会返回满足条件的部门列表.
-- 2. 查询员工中工资大于本部门平均工资的员工信息(员工id, 薪资, 部门id):
-- 2.1 查询每个部门的平均工资(子查询):
SELECT AVG(salary) FROM employees AS `sub_emp`;

-- 2.2 通过主查询提供部门id查找对应的平均工资(完整子查询):
SELECT AVG(salary) FROM employees AS `sub_emp` 
WHERE sub_empemp.department_id = main_emp.department_id; -- 关联条件

-- 2.3 查询员工的信息(主查询):
SELECT employee_id, salary, department_id FROM employees  AS `main_emp`;

-- 2.4 查询员工工资大于xx(自己部门的平均工资)的员工信息(完整主查询):
SELECT employee_id, salary, department_id FROM employees AS `main_emp`
WHERE salary > ();

-- 2.5 语句合并:
SELECT employee_id, salary, department_id FROM employees AS `main_emp`
WHERE salary > (
    SELECT AVG(salary) FROM employees  AS `sub_emp` 
    WHERE sub_emp.department_id = main_emp.department_id
) ORDER BY department_id, salary;
+-------------+----------+---------------+
| employee_id | salary   | department_id |
+-------------+----------+---------------+
|         201 | 13000.00 |            20 |
|         114 | 11000.00 |            30 |
|         141 |  3500.00 |            50 |
|         189 |  3600.00 |            50 |
|         137 |  3600.00 |            50 |
|         188 |  3800.00 |            50 |
|         ... |     ...  |           ... |  -- 省略
|         145 | 14000.00 |            80 |
|         100 | 24000.00 |            90 |
|         109 |  9000.00 |           100 |
|         108 | 12000.00 |           100 |
|         205 | 12000.00 |           110 |
+-------------+----------+---------------+
38 rows in set (0.01 sec)

-- 验证一下: 
SELECT employee_id, department_id, salary, avg_salary 
FROM employees AS `main_emp`
INNER JOIN (
    SELECT  department_id, AVG(salary) AS `avg_salary` 
    FROM employees GROUP BY department_id) AS `avg_salary_table` -- 表子查询必须要有别名!!!
    USING (department_id)
WHERE salary > avg_salary;
...
38 rows in set (0.00 sec)
-- 3. 查询员工id, 工资, 按照department_name排序:
-- 3.1 查询部门名称(子查询):
SELECT department_name FROM departments AS `sub_dep`;

-- 3.2 通过主查询提供部门id查询对应的部门名称(完整子查询):
SELECT department_name FROM departments AS `sub_dep`
WHERE sub_dep.department_id = main_emp.department_id;  -- 关联条件

-- 3.3 查询员工id, 工资(主查询):
SELECT employee_id, salary FROM employees AS `main_emp`;

-- 3.4 获取的员工信息按照部门名称排序(完整主查询):
SELECT employee_id, salary FROM employees AS `main_emp`
ORDER BY ();

-- 3.5 语句合并:
SELECT employee_id, salary FROM employees AS `main_emp`
ORDER BY (
    SELECT department_name FROM departments AS `sub_dep` -- 子查询返回部门名称给ORDER BY进行排序
    WHERE sub_dep.department_id = main_emp.department_id );
+-------------+----------+
| employee_id | salary   |
+-------------+----------+
|         178 |  7000.00 |
|         205 | 12000.00 |
|         206 |  8300.00 |
|         200 |  4400.00 |
|         ... |      ... | -- 省略
|         196 |  3100.00 |
|         197 |  3000.00 |
|         198 |  2600.00 |
|         199 |  2600.00 |
+-------------+----------+
107 rows in set (0.00 sec)

-- 验证
SELECT employee_id, salary, department_name 
FROM employees
LEFT JOIN departments -- 注意Null
USING (department_id)
ORDER BY department_name;
+-------------+----------+------------------+
| employee_id | salary   | department_name  |
+-------------+----------+------------------+
|         178 |  7000.00 | NULL             |  -- 排序中有NULL则
|         205 | 12000.00 | Accounting       |
|         206 |  8300.00 | Accounting       |
|         200 |  4400.00 | Administration   |
|         ... |      ... | ...              |  -- 省略
|         196 |  3100.00 | Shipping         |
|         197 |  3000.00 | Shipping         |
|         198 |  2600.00 | Shipping         |
|         199 |  2600.00 | Shipping         |
+-------------+----------+------------------+
107 rows in set (0.00 sec)
-- 4. 若employees表中employee_id与job_history表中employee_id相同的数目不小于2, 
-- 输出这些相同id的员工信息(员工id, 名字, 岗位id):
-- 看一下job_history表的信息(工作变迁记录, 记录一条表示工作岗位变迁一次):
mysql> SELECT * FROM job_history;
+-------------+------------+------------+------------+---------------+
| employee_id | start_date | end_date   | job_id     | department_id |
+-------------+------------+------------+------------+---------------+
|         101 | 1989-09-21 | 1993-10-27 | AC_ACCOUNT |           110 |
|         101 | 1993-10-28 | 1997-03-15 | AC_MGR     |           110 |
|         102 | 1993-01-13 | 1998-07-24 | IT_PROG    |            60 |
|         114 | 1998-03-24 | 1999-12-31 | ST_CLERK   |            50 |
|         122 | 1999-01-01 | 1999-12-31 | ST_CLERK   |            50 |
|         176 | 1998-03-24 | 1998-12-31 | SA_REP     |            80 |
|         176 | 1999-01-01 | 1999-12-31 | SA_MAN     |            80 |
|         200 | 1987-09-17 | 1993-06-17 | AD_ASST    |            90 |
|         200 | 1994-07-01 | 1998-12-31 | AC_ACCOUNT |            90 |
|         201 | 1996-02-17 | 1999-12-19 | MK_REP     |            20 |
+-------------+------------+------------+------------+---------------+
10 rows in set (0.02 sec)

-- 这道题的就说查询岗位变动超过两次的员工信息.
-- 4.1 统计员工岗位变迁的次数(子查询):
SELECT COUNT(*) FROM job_history AS `sub_job`;

-- 4.2 通过主查询的提供的员工id获取对应的统计信息(完整子查询):
SELECT COUNT(*) FROM job_history AS `sub_job` 
WHERE sub_job.employee_id = main_emp.employee_id;

-- 4.3 查询工信息(主查询):
SELECT employee_id, first_name, job_id FROM employees AS `main_emp`;

-- 4.4 查询员工岗位变动超过或等于2次的员工信息(完整主查询):
SELECT employee_id, first_name, job_id FROM employees AS `main_emp`
WHERE 2 <= ();

-- 4.5 语句合并:
SELECT employee_id, first_name, job_id FROM employees AS `main_emp`
WHERE 2 <= (
    SELECT COUNT(*) FROM job_history AS `sub_job` 
    WHERE sub_job.employee_id = main_emp.employee_id
);
+-------------+------------+---------+
| employee_id | first_name | job_id  |
+-------------+------------+---------+
|         101 | Neena      | AD_VP   |
|         176 | Jonathon   | SA_REP  |
|         200 | Jennifer   | AD_ASST |
+-------------+------------+---------+
3 rows in set (0.01 sec)

5.3 相关子查询中的空值

在SQL中, 当使用相关子查询时, 如果主查询中的某个值在子查询中没有对应的值, 那么子查询的返回结果将为NULL.
-- 查询每个部门的平均工资和和部门名称:
mysql> SELECT department_id, department_name, (
    SELECT AVG(salary) FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_dep.department_id  -- 没有对应的值将返回NULL
) AS `avg_salary` FROM departments AS `main_dep`;
+---------------+----------------------+--------------+
| department_id | department_name      | avg_salary   |
+---------------+----------------------+--------------+
|            10 | Administration       |  4400.000000 |
|            20 | Marketing            |  9500.000000 |
|            30 | Purchasing           |  4150.000000 |
|           200 | ...                  |          ... |  -- 省略
|           210 | IT Support           |         NULL |
|           220 | NOC                  |         NULL |
|           230 | IT Helpdesk          |         NULL |
|           240 | Government Sales     |         NULL |
|           250 | Retail Sales         |         NULL |
|           260 | Recruiting           |         NULL |
|           270 | Payroll              |         NULL |
+---------------+----------------------+--------------+
27 rows in set (0.00 sec)
出现NULL值的原因是在sub_emp子查询中, 对于某些department_id在employees表中没有对应的记录,
因此子查询没有返回任何值, 导致avg_salary列的值为NULL.
这种行为是由SQL的查询处理模型决定的. 
SELECT department_id, department_name, (
    SELECT AVG(salary) FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_dep.department_id  -- 没有对应的值将返回NULL
) AS `avg_salary` FROM departments AS `main_dep`
WHERE department_id IN ( SELECT department_id FROM employees );  -- 不让employees表中没有匹配的值进入子查询
+---------------+------------------+--------------+
| department_id | department_name  | avg_salary   |
+---------------+------------------+--------------+
|            10 | Administration   |  4400.000000 |
|            20 | Marketing        |  9500.000000 |
|            30 | Purchasing       |  4150.000000 |
|            40 | Human Resources  |  6500.000000 |
|            50 | Shipping         |  3475.555556 |
|            60 | IT               |  5760.000000 |
|            70 | Public Relations | 10000.000000 |
|            80 | Sales            |  8955.882353 |
|            90 | Executive        | 19333.333333 |
|           100 | Finance          |  8600.000000 |
|           110 | Accounting       | 10150.000000 |
+---------------+------------------+--------------+
11 rows in set (0.00 sec)

5.4 EXISTS和NOT EXISTS关键字

EXISTS和NOT EXISTS是SQL中用于检查子查询是否返回任何结果的关键字.
这两个关键字常用于WHERE子句中, 以基于子查询的结果来过滤外部查询的行.

EXISTS关键字: 用于检查子查询是否至少返回一行数据.
如果子查询至少返回一行, EXISTS的结果为TRUE; 如果子查询没有返回任何行, EXISTS的结果为FALSE.

NOT EXISTS关键字: 用于检查子查询是否不返回任何行.
如果子查询没有返回任何行, NOT EXISTS 的结果为 TRUE; 如果子查询返回了至少一行, NOT EXISTS的结果为FALSE.

注意事项:
* 1. 在EXISTS和NOT EXISTS的子查询中, 通常使用 SELECT 1,
     因为实际上我们并不关心子查询返回的具体数据, 只关心它是否返回了数据.
* 2. 使用EXISTS和NOT EXISTS通常比使用IN或NOT IN在性能上更优, 特别是在处理大量数据时,
     因为一旦子查询找到匹配的行, 它就会立即停止搜索并返回结果.
* 3. 当使用这些关键字时, 确保子查询的逻辑是正确的, 以避免返回不期望的结果.

* 在MySQL中, 某些情况下可以使用EXISTS和NOT EXISTS关键字来代替IN或NOT IN的查询语句.
-- 1. 查询公司管理者的employee_id, first_name, job_id, department_id信息:
-- 方式1, 自连接(查看员工表可知, 某些员工管理多个员工, 注意去重):
SELECT DISTINCT emp1.employee_id, emp1.first_name, emp1.job_id, emp1.department_id 
FROM employees AS `emp1`
INNER JOIN employees AS `emp2` 
ON emp1.employee_id = emp2.manager_id;
+-------------+------------+---------+---------------+
| employee_id | first_name | job_id  | department_id |
+-------------+------------+---------+---------------+
|         100 | Steven     | AD_PRES |            90 |
|         101 | Neena      | AD_VP   |            90 |
|         102 | Lex        | AD_VP   |            90 |
|         103 | Alexander  | IT_PROG |            60 |
|         108 | Nancy      | FI_MGR  |           100 |
|         114 | Den        | PU_MAN  |            30 |
|         120 | Matthew    | ST_MAN  |            50 |
|         121 | Adam       | ST_MAN  |            50 |
|         122 | Payam      | ST_MAN  |            50 |
|         123 | Shanta     | ST_MAN  |            50 |
|         124 | Kevin      | ST_MAN  |            50 |
|         145 | John       | SA_MAN  |            80 |
|         146 | Karen      | SA_MAN  |            80 |
|         147 | Alberto    | SA_MAN  |            80 |
|         148 | Gerald     | SA_MAN  |            80 |
|         149 | Eleni      | SA_MAN  |            80 |
|         201 | Michael    | MK_MAN  |            20 |
|         205 | Shelley    | AC_MGR  |           110 |
+-------------+------------+---------+---------------+
18 rows in set (0.01 sec)

-- 方式2, IN关键字(已经知晓有重复的数据就手动去重, 增加效率):
SELECT employee_id, first_name, job_id, department_id FROM employees 
WHERE employee_id IN ( SELECT DISTINCT manager_id FROM employees );

-- 方式3, EXISTS关键字(不需要关系子查询数据重复问题).
-- 主查询提供员工id到子查询自上往下匹配, 匹配成功则返回True.
SELECT employee_id, first_name, job_id, department_id 
FROM employees AS `main_emp`
WHERE EXISTS (
    SELECT 1 FROM employees AS `sub_emp` 
    WHERE sub_emp.manager_id = main_emp.employee_id ); 
+-------------+------------+---------+---------------+
| employee_id | first_name | job_id  | department_id |
+-------------+------------+---------+---------------+
|         100 | Steven     | AD_PRES |            90 |
|         101 | Neena      | AD_VP   |            90 |
|         102 | Lex        | AD_VP   |            90 |
|         103 | Alexander  | IT_PROG |            60 |
|         108 | Nancy      | FI_MGR  |           100 |
|         114 | Den        | PU_MAN  |            30 |
|         120 | Matthew    | ST_MAN  |            50 |
|         121 | Adam       | ST_MAN  |            50 |
|         122 | Payam      | ST_MAN  |            50 |
|         123 | Shanta     | ST_MAN  |            50 |
|         124 | Kevin      | ST_MAN  |            50 |
|         145 | John       | SA_MAN  |            80 |
|         146 | Karen      | SA_MAN  |            80 |
|         147 | Alberto    | SA_MAN  |            80 |
|         148 | Gerald     | SA_MAN  |            80 |
|         149 | Eleni      | SA_MAN  |            80 |
|         201 | Michael    | MK_MAN  |            20 |
|         205 | Shelley    | AC_MGR  |           110 |
+-------------+------------+---------+---------------+
18 rows in set (0.00 sec)
-- 2. 查询departments表中, 不存在于employees表中的部门的department_id和department_name(意思就是查询空闲的部门).
-- 拿部门表的部门id去员工表中查询是否存在:
SELECT department_id, department_name FROM departments AS `main_dep`
WHERE NOT EXISTS (
   SELECT 1 FROM employees AS `sub_emp` 
    WHERE sub_emp.department_id = main_dep.department_id );
+---------------+----------------------+
| department_id | department_name      |
+---------------+----------------------+
|           120 | Treasury             |
|           130 | Corporate Tax        |
|           140 | Control And Credit   |
|           150 | Shareholder Services |
|           160 | Benefits             |
|           170 | Manufacturing        |
|           180 | Construction         |
|           190 | Contracting          |
|           200 | Operations           |
|           210 | IT Support           |
|           220 | NOC                  |
|           230 | IT Helpdesk          |
|           240 | Government Sales     |
|           250 | Retail Sales         |
|           260 | Recruiting           |
|           270 | Payroll              |
+---------------+----------------------+
16 rows in set (0.01 sec)

5.5 相关更新

使用相关子查询依据一个表中的数据更新另一个表的数据.
-- 相关更新格式:
UPDATE table1 alias1
SET  column = ( SELECT expression
    FROM  table2 alias2
    WHERE alias1.column = alias2.column );
-- 不要执行!!!
-- 例: 在employees中增加一个department_name字段, 数据为员工对应的部门名称:
-- 1. 增加字段, 此时employees表中的department_name数据为NULL
ALTER TABLE employees
ADD( department_name VARCHAR(24) );
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

-- 2. 将NULL更改为对应的部门名称:
UPDATE employees AS `emp`
SET department_name = ( SELECT department_name
    FROM  departments AS `dep`
    WHERE emp.department_id = dep.department_id );
Query OK, 106 rows affected (0.01 sec)
Rows matched: 107  Changed: 106  Warnings: 0

-- 3. 查询员工表:
SELECT employee_id, first_name, department_id, department_name FROM employees;
+-------------+-------------+---------------+------------------+
| employee_id | first_name  | department_id | department_name  |
+-------------+-------------+---------------+------------------+
|         100 | Steven      |            90 | Executive        |
|         101 | Neena       |            90 | Executive        |
|         102 | Lex         |            90 | Executive        |
|         103 | Alexander   |            60 | IT               |
|         104 | Bruce       |            60 | IT               |
|         105 | David       |            60 | IT               |
+-------------+-------------+---------------+------------------+
107 rows in set (0.00 sec)

5.6 相关删除

使用相关子查询依据一个表中的数据删除另一个表的数据.
-- 相关删除格式:
DELETE FROM table1 alias1
WHERE column operator ( SELECT expression
    FROM  table2 alias2
    WHERE alias1.column = alias2.column );
-- 不要执行!!!
-- 删除employees表中, 在job_history表中有记录的信息:
DELETE FROM employees AS `main_emp` 
WHERE EXISTS (
    SELECT employee_id FROM job_history AS `sub_history`
    WHERE main_emp.employee_id = sub_history.employee_id 
);

-- 使用查询语句替换删除语句来验证找到的数据:
SELECT employee_id FROM employees AS `main_emp` 
WHERE EXISTS (
    SELECT employee_id FROM job_history AS `sub_history`
    WHERE sub_history.employee_id = main_emp.employee_id );
+-------------+
| employee_id |
+-------------+
|         101 |
|         102 |
|         114 |
|         122 |
|         176 |
|         200 |
|         201 |
+-------------+
7 rows in set (0.00 sec)
-- 我遇到的错误(粗心啊: 忘记表中返回多条数据, 记录一下自己呆呆的时候, 以后看到笑话下自己):
SELECT department_id FROM employees AS `main_emp` 
WHERE employee_id = (
    SELECT employee_id FROM job_history AS `sub_history`
    WHERE sub_history.employee_id = main_emp.employee_id );  -- 它的执行依赖于外部查询
ERROR 1242 (21000): Subquery returns more than 1 row  
-- 提示返回了多个值, 多行子查询不能使用等号.
-- 原因: job_history表中有多条记录具有相同的employee_id, 这个语句就是相关子查询每个返回多条数据!!!

-- 修改, 使用多行子查询操作符:
+---------------+
| department_id |
+---------------+
|            20 |
|            30 |
|            50 |
|            90 |
|            80 |
|            10 |
|            90 |
+---------------+
7 rows in set (0.00 sec)

6. 练习

很多题目读起来很变扭, 思来想去为什么? , 是为了锻炼小朋友.

6.1 题1

-- 1. 查询与Eleni(first_name)相同部门的员工信息(名字, 工资, 部门id):
-- 1.1 查询Eleni的部门id:
mysql> SELECT department_id from employees WHERE first_name = 'Eleni';
+---------------+
| department_id |
+---------------+
|            80 |
+---------------+
1 row in set (0.00 sec)

-- 1.2 查询部门id为50的员工信息:
SELECT first_name, salary, department_id FROM employees 
WHERE department_id =  (
    SELECT department_id from employees WHERE first_name = 'Eleni'
);
+-------------+----------+---------------+
| first_name  | salary   | department_id |
+-------------+----------+---------------+
| John        | 14000.00 |            80 |
| Karen       | 13500.00 |            80 |
| Elizabeth   |  7300.00 |            80 |
| Sundita     |  6100.00 |            80 |
| ...         |     ...  |           ... | -- 省略
| Alyssa      |  8800.00 |            80 |
| Jonathon    |  8600.00 |            80 |
| Jack        |  8400.00 |            80 |
| Charles     |  6200.00 |            80 |
+-------------+----------+---------------+
34 rows in set (0.00 sec)

6.2 题2

-- 2. 查询工资比公司平均工资高的员工信息(员工号, 名字, 工资):
-- 2.1 查询公司的平均工资:
mysql> SELECT AVG(salary) FROM employees;
+-------------+
| AVG(salary) |
+-------------+
| 6461.682243 |
+-------------+
1 row in set (0.00 sec)

-- 2.2 查询工资比6461高的员工信息"
SELECT employee_id, first_name, salary FROM employees 
WHERE salary > (
    SELECT AVG(salary) FROM employees 
) ORDER BY salary;
+-------------+-------------+----------+
| employee_id | first_name  | salary   |
+-------------+-------------+----------+
|         203 | Susan       |  6500.00 |
|         123 | Shanta      |  6500.00 |
|         ... | ...         |      ... |  -- 省略
|         146 | Karen       | 13500.00 |
|         145 | John        | 14000.00 |
|         101 | Neena       | 17000.00 |
|         102 | Lex         | 17000.00 |
|         100 | Steven      | 24000.00 |
+-------------+-------------+----------+
51 rows in set (0.00 sec)

6.3 题3

-- 3. 选择工资大于所有JOB_ID = 'SA_MAN'的员工的工资的员工信息(名字, 岗位id, 薪资):
-- 3.1 查询SA_MAN的部门所有员工的薪资:
mysql> SELECT salary FROM employees WHERE job_id = 'SA_MAN';
+----------+
| salary   |
+----------+
| 14000.00 |
| 13500.00 |
| 12000.00 |
| 11000.00 |
| 10500.00 |
+----------+
5 rows in set (0.00 sec)

-- 3.2 查询工资大于xx(x1, x2, x3, ...)的员工信息:
SELECT first_name, job_id, salary FROM employees 
WHERE salary > ALL (
    SELECT salary FROM employees WHERE job_id = 'SA_MAN'
);
+------------+---------+----------+
| first_name | job_id  | salary   |
+------------+---------+----------+
| Steven     | AD_PRES | 24000.00 |
| Neena      | AD_VP   | 17000.00 |
| Lex        | AD_VP   | 17000.00 |
+------------+---------+----------+
3 rows in set (0.00 sec)

6.4 题4

-- 4. 查询和姓名(last_name)中包含字母u的员工在相同部门的员工信息(员工号, 姓名, 部门id):
-- 4.1 查询名称包含字母u的员工部门id:
mysql> SELECT department_id FROM employees WHERE last_name LIKE '%u%';
+---------------+
| department_id |
+---------------+
|            60 |  -- 注意去重
|            60 |
|           ... |  -- 省略
|            30 |
|            50 |
|            50 |
|            50 |
+---------------+
19 rows in set (0.00 sec)

-- 4.2 查询xx(x1, x2, x3, ...)部门下的员工信息:
mysql> SELECT employee_id, salary, department_id FROM employees
WHERE department_id IN (
    SELECT DISTINCT department_id FROM employees WHERE last_name LIKE '%u%'
);
+-------------+----------+---------------+
| employee_id | salary   | department_id |
+-------------+----------+---------------+
|         103 |  9000.00 |            60 |
|         104 |  6000.00 |            60 |
|         105 |  4800.00 |            60 |
|         ... |      ... |           ... |  -- 省略
|         175 |  8800.00 |            80 |
|         176 |  8600.00 |            80 |
|         177 |  8400.00 |            80 |
|         179 |  6200.00 |            80 |
+-------------+----------+---------------+
96 rows in set (0.00 sec)

6.5 题5

-- 5. 查询在部门的location_id为1700的部门工作的员工信息(员工号):
-- 5.1 查询部门地址为1700的部门id:
mysql> SELECT department_id FROM departments WHERE location_id = '1700';
+---------------+
| department_id |
+---------------+
|            10 |
|            30 |
|            90 |
|           ... |  -- 省略
|           240 |
|           250 |
|           260 |
|           270 |
+---------------+
21 rows in set (0.00 sec)

-- 5.2 查询部门id为xx(x1, x2, x3, ...)的员工信息:
mysql> SELECT employee_id FROM employees 
WHERE department_id IN (
    SELECT department_id FROM departments WHERE location_id = '1700'
);
+-------------+
| employee_id |
+-------------+
|         200 |
|         114 |
|         ... |  -- 省略
|         112 |
|         113 |
|         205 |
|         206 |
+-------------+
18 rows in set (0.00 sec)

6.6 题6

-- 6. 查询管理者是King(last_name)的员工信息(名字, 工资):
-- 6.1 查询King的id:
mysql> SELECT employee_id FROM employees WHERE last_name = 'King';
+-------------+
| employee_id |
+-------------+
|         100 |
|         156 |
+-------------+
2 rows in set (0.00 sec)

-- 6.2 查询manager_id为xx的员工信息:
mysql> SELECT first_name, salary FROM employees
WHERE manager_id IN (
    SELECT employee_id FROM employees WHERE last_name = 'King'
);
+------------+----------+
| first_name | salary   |
+------------+----------+
| Neena      | 17000.00 |
| Lex        | 17000.00 |
| ...        |      ... |  -- 省略
| Alberto    | 12000.00 |
| Gerald     | 11000.00 |
| Eleni      | 10500.00 |
| Michael    | 13000.00 |
+------------+----------+
14 rows in set (0.00 sec)

6.7 题7

-- 7. 查询工资最低的员工信息(名字, 薪资):
-- 7.1 查询最新工资:
mysql> SELECT MIN(salary) FROM employees;
+-------------+
| MIN(salary) |
+-------------+
|     2100.00 |
+-------------+
1 row in set (0.00 sec)

-- 7.2 查询工资为xx的员工信息:
SELECT first_name, salary FROM employees 
WHERE salary =  (
    SELECT MIN(salary) FROM employees
);
+------------+---------+
| first_name | salary  |
+------------+---------+
| TJ         | 2100.00 |
+------------+---------+
1 row in set (0.00 sec)


-- 排序法:
mysql> SELECT first_name, salary FROM employees
       ORDER BY salary LIMIT 1;
+------------+---------+
| first_name | salary  |
+------------+---------+
| TJ         | 2100.00 |
+------------+---------+
1 row in set (0.00 sec)

6.8 题8

-- 8. 查询平均工资最低的部门信息(部门id, 部门名称):
-- 8.1 查询部门的平均工资:
mysql> SELECT AVG(salary) AS `avg_salary` 
FROM employees GROUP BY department_id;
+--------------+
| avg_salary   |
+--------------+
|  7000.000000 |
|  4400.000000 |
|          ... |  -- 省略
| 10150.000000 |
+--------------+
12 rows in set (0.00 sec)

-- 8.2 最低的平均工资:
mysql> SELECT MIN(avg_salary) FROM (
    SELECT AVG(salary) AS `avg_salary` 
    FROM employees GROUP BY department_id
) AS `avg_salary_table`;
+-----------------+
| MIN(avg_salary) |
+-----------------+
|     3475.555556 |
+-----------------+
1 row in set (0.00 sec)

-- 8.3 查询平均工资为3475的部门id:
mysql> SELECT department_id FROM employees
GROUP BY department_id
HAVING AVG(salary) = (
    SELECT MIN(avg_salary) FROM (
        SELECT AVG(salary) AS `avg_salary` 
        FROM employees GROUP BY department_id
    ) AS `avg_salary_table`
);
+---------------+
| department_id |
+---------------+
|            50 |
+---------------+
1 row in set (0.00 sec)

-- 8.4 通过部门id获取部门信息:
mysql> SELECT department_id, department_name FROM departments
WHERE department_id = (
	SELECT department_id FROM employees
    GROUP BY department_id
    HAVING AVG(salary) = (
        SELECT MIN(avg_salary) FROM (
            SELECT AVG(salary) AS `avg_salary` 
            FROM employees GROUP BY department_id
        ) AS `avg_salary_table`
    )
);
+---------------+-----------------+
| department_id | department_name |
+---------------+-----------------+
|            50 | Shipping        |
+---------------+-----------------+
1 row in set (0.00 sec)

-- 方式二:
-- x.1 获取最低平均工资:
mysql> SELECT department_id, AVG(salary) AS `avg_salary` FROM employees
GROUP BY department_id
ORDER BY avg_salary
LIMIT 1;
+---------------+-------------+
| department_id | avg_salary  |
+---------------+-------------+
|            50 | 3475.555556 |
+---------------+-------------+
1 row in set (0.00 sec)

-- x.2 单独取出部门id(LIMIT只取出一条数据, 不用考虑过滤条件):
SELECT department_id FROM (
    SELECT department_id, AVG(salary) AS `avg_salary` FROM employees
    GROUP BY department_id
    ORDER BY avg_salary
    LIMIT 1
) AS `min_avg_salary_table`;
+---------------+
| department_id |
+---------------+
|            50 |
+---------------+
1 row in set (0.00 sec)

-- x.3 通过部门id获取部门信息:
mysql> SELECT department_id, department_name FROM departments
WHERE department_id = (
	SELECT department_id FROM (
        SELECT department_id, AVG(salary) AS `avg_salary` FROM employees
        GROUP BY department_id
        ORDER BY avg_salary
        LIMIT 1
    ) AS `min_avg_salary_table`
); 
+---------------+-----------------+
| department_id | department_name |
+---------------+-----------------+
|            50 | Shipping        |
+---------------+-----------------+
1 row in set (0.00 sec)

6.9 题9

-- 9. 查询平均工资最低的部门信息和该部门的平均工资(相关子查询):
-- 9.1 查询部门的平均工资:
mysql> SELECT department_id, AVG(salary) AS `avg_salary` 
FROM employees AS `sub_emp`
GROUP BY department_id;
+---------------+--------------+
| department_id | avg_salary   |
+---------------+--------------+
|          NULL |  7000.000000 |
|            10 |  4400.000000 |
|            90 | 19333.333333 |
|           ... |          ... |  -- 省略
|           110 | 10150.000000 |
+---------------+--------------+
12 rows in set (0.00 sec)

-- 9.2 相关子查询获取部门的平均工资:
mysql> SELECT department_id, (
    SELECT AVG(salary) AS `avg_salary` 
    FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_dep.department_id  -- 没有对应的值将返回NULL
) AS `avg_salary` FROM departments AS main_dep;
+---------------+--------------+
| department_id | avg_salary   |
+---------------+--------------+
|            10 |  4400.000000 |
|            20 |  9500.000000 |
|            30 |  4150.000000 |
|           ... |         ...  |
|           130 |         NULL |
|           140 |         NULL |
|           150 |         NULL |
|           160 |         NULL |
|           170 |         NULL |
+---------------+--------------+

-- 9.3 过滤NULL值:
mysql> SELECT department_id, department_name, (
    SELECT AVG(salary) FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_dep.department_id  -- 没有对应的值将返回NULL
) AS `avg_salary` FROM departments AS `main_dep`
WHERE department_id IN ( SELECT department_id FROM employees );  -- 过滤没有员工的部门
+---------------+------------------+--------------+
| department_id | department_name  | avg_salary   |
+---------------+------------------+--------------+
|            10 | Administration   |  4400.000000 |
|            20 | Marketing        |  9500.000000 |
|            30 | Purchasing       |  4150.000000 |
|            40 | Human Resources  |  6500.000000 |
|            50 | Shipping         |  3475.555556 |
|            60 | IT               |  5760.000000 |
|            70 | Public Relations | 10000.000000 |
|            80 | Sales            |  8955.882353 |
|            90 | Executive        | 19333.333333 |
|           100 | Finance          |  8600.000000 |
|           110 | Accounting       | 10150.000000 |
+---------------+------------------+--------------+
11 rows in set (0.00 sec)

-- 9.4 排序并获取低工资的部门信息:
mysql> SELECT department_id, department_name, (
    SELECT AVG(salary) FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_dep.department_id  -- 没有对应的值将返回NULL
) AS `avg_salary` FROM departments AS `main_dep`
WHERE department_id IN ( SELECT department_id FROM employees )
ORDER BY avg_salary
LIMIT 1;
+---------------+-----------------+-------------+
| department_id | department_name | avg_salary  |
+---------------+-----------------+-------------+
|            50 | Shipping        | 3475.555556 |
+---------------+-----------------+-------------+
1 row in set (0.00 sec)

6.10 题10

-- 下面用到jobs表:
mysql> SELECT * FROM jobs;
+------------+---------------------------------+------------+------------+
| job_id     | job_title                       | min_salary | max_salary |
+------------+---------------------------------+------------+------------+
| AC_ACCOUNT | Public Accountant               |       4200 |       9000 |
|        ... | ...                             |        ... |        ... |  -- 省略
+------------+---------------------------------+------------+------------+
 -- 10. 查询平均工资最高的job信息:
 -- 10.1 按岗位分组计算平均工资:
mysql>  SELECT job_id, AVG(salary) FROM employees GROUP BY job_id;
+------------+--------------+
| job_id     | AVG(salary)  |
+------------+--------------+
| AC_ACCOUNT |  8300.000000 |
| AC_MGR     | 12000.000000 |
| ...        |          ... |  -- 省略
| SH_CLERK   |  3215.000000 |
| ST_CLERK   |  2785.000000 |
| ST_MAN     |  7280.000000 |
+------------+--------------+
19 rows in set (0.00 sec)

-- 10.2 获取工资最高的部门信息:
mysql> SELECT job_id, AVG(salary) as `avg_salary`
    FROM employees
    GROUP BY job_id
    ORDER BY avg_salary DESC  -- 设置为倒序
    LIMIT 1;  -- 求最高的工资
+---------+--------------+
| job_id  | avg_salary   |
+---------+--------------+
| AD_PRES | 24000.000000 |
+---------+--------------+
1 row in set (0.00 sec)

-- 10.3 获取工资最高的部门id:
mysql> SELECT job_id FROM (
    SELECT job_id, AVG(salary) as `avg_salary`
        FROM employees
        GROUP BY job_id
        ORDER BY avg_salary DESC  -- 设置为倒序
        LIMIT 1
) AS `max_salary_table`;
+---------+
| job_id  |
+---------+
| AD_PRES |
+---------+
1 row in set (0.00 sec)

-- 10.4 通过job_id获取岗位信息:
mysql> SELECT * FROM jobs 
WHERE job_id = (
SELECT job_id FROM (
    SELECT job_id, AVG(salary) as `avg_salary`
        FROM employees
        GROUP BY job_id
        ORDER BY avg_salary DESC  -- 设置为倒序
        LIMIT 1
    ) AS `max_salary_table`
);
+---------+-----------+------------+------------+
| job_id  | job_title | min_salary | max_salary |
+---------+-----------+------------+------------+
| AD_PRES | President |      20000 |      40000 |
+---------+-----------+------------+------------+


-- 方式2: 相关子查询
mysql> SELECT *, (
    SELECT AVG(salary) FROM employees AS `sub_emp`
    WHERE sub_emp.job_id = main_jobs.job_id  -- 这里不会出现NULL值
) AS `avg_salary` FROM jobs AS `main_jobs`
ORDER BY avg_salary DESC
LIMIT 1;
+---------+-----------+------------+------------+--------------+
| job_id  | job_title | min_salary | max_salary | avg_salary   |
+---------+-----------+------------+------------+--------------+
| AD_PRES | President |      20000 |      40000 | 24000.000000 |
+---------+-----------+------------+------------+--------------+
1 row in set (0.00 sec)

6.11 题11

-- 11. 查询平均工资高于公司平均工资的部门有哪些?
-- 11.1 查询工资平均工资:
mysql> SELECT AVG(salary) AS `avg_salary` FROM employees;
+-------------+
| avg_salary  |
+-------------+
| 6461.682243 |
+-------------+
1 row in set (0.00 sec)

-- 11.2 查询部门平均工资:
mysql> SELECT department_id, AVG(salary) FROM employees
GROUP BY department_id;
+---------------+--------------+
| department_id | AVG(salary)  |
+---------------+--------------+
|          NULL |  7000.000000 |
|            10 |  4400.000000 |
|            20 |  9500.000000 |
|            90 | 19333.333333 |
|           ... |          ... |  -- 省略
|           110 | 10150.000000 |
+---------------+--------------+
12 rows in set (0.00 sec)

-- 11.3 查询部门平均工资大于公司平均工资的:
SELECT department_id, AVG(salary) AS `dep_avg_salary` FROM employees
GROUP BY department_id
HAVING dep_avg_salary > (
    SELECT AVG(salary) AS `avg_salary` FROM employees
);
+---------------+----------------+
| department_id | dep_avg_salary |
+---------------+----------------+
|          NULL |    7000.000000 |  -- 没有部门
|            20 |    9500.000000 |
|            40 |    6500.000000 |
|            70 |   10000.000000 |
|            80 |    8955.882353 |
|            90 |   19333.333333 |
|           100 |    8600.000000 |
|           110 |   10150.000000 |
+---------------+----------------+
8 rows in set (0.00 sec)

-- 11.4 通过部门id获取部门名称:
SELECT department_id, department_name FROM departments AS `main_dep`
WHERE EXISTS (
    SELECT 1 FROM (
        SELECT department_id, AVG(salary) AS `dep_avg_salary` FROM employees
        GROUP BY department_id
        HAVING dep_avg_salary > (
            SELECT AVG(salary) AS `avg_salary` FROM employees
        ) 
    ) AS `sub_emp` 
    WHERE sub_emp.department_id = main_dep.department_id
);
+---------------+------------------+
| department_id | department_name  |
+---------------+------------------+
|            20 | Marketing        |
|            40 | Human Resources  |
|            70 | Public Relations |
|            80 | Sales            |
|            90 | Executive        |
|           100 | Finance          |
|           110 | Accounting       |
+---------------+------------------+
7 rows in set (0.00 sec)

6.12 题12

-- 12. 查询出公司中所有manager的详细信息.
-- 12.1 查询有管理者的员工id:
mysql> SELECT DISTINCT manager_id FROM employees;
+------------+
| manager_id |
+------------+
|       NULL |
|        100 |
|        ... |  -- 省略
|        201 |
|        205 |
+------------+
19 rows in set (0.00 sec)

-- 12.2 排除NULL:
mysql> SELECT DISTINCT manager_id FROM employees 
WHERE manager_id IS NOT NULL;
+------------+
| manager_id |
+------------+
|        100 |
|        ... |  -- 省略
|        201 |
|        205 |
+------------+
18 rows in set (0.00 sec)

-- 12.3 通过管理者获取员工信息(员工id, 名字, 薪资, 管理者id):
mysql> SELECT employee_id, first_name, salary, manager_id FROM employees
WHERE employee_id IN (
    SELECT DISTINCT manager_id FROM employees
    WHERE manager_id IS NOT NULL
);
+-------------+------------+----------+------------+
| employee_id | first_name | salary   | manager_id |
+-------------+------------+----------+------------+
|         100 | Steven     | 24000.00 |       NULL |
|         101 | Neena      | 17000.00 |        100 |
|         ... | ...        |     ...  |        ... |  -- 省略
|         103 | Alexander  |  9000.00 |        102 |
|         149 | Eleni      | 10500.00 |        100 |
|         201 | Michael    | 13000.00 |        100 |
|         205 | Shelley    | 12000.00 |        101 |
+-------------+------------+----------+------------+
18 rows in set (0.00 sec)

-- 或:
SELECT employee_id, first_name, salary, manager_id 
FROM employees AS `main_emp`
WHERE EXISTS (
    SELECT 1 FROM employees AS `sub_emp`
    WHERE sub_emp.manager_id = main_emp.employee_id
);

6.13 题13

-- 13. 各个部门中最高工资中最低的那个部门的 最低工资是多少?
-- 13.1 查询各部门的最高工资:
mysql> SELECT department_id, MAX(salary) FROM employees
GROUP BY department_id;
+---------------+-------------+
| department_id | MAX(salary) |
+---------------+-------------+
|          NULL |     7000.00 |
|            10 |     4400.00 |
|           ... |      .   .. |  -- 省略
|           110 |    12000.00 |
+---------------+-------------+
12 rows in set (0.00 sec)

-- 13.2 排除部门为NULL的信息:
mysql> SELECT department_id, MAX(salary) FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id;
+---------------+-------------+
| department_id | MAX(salary) |
+---------------+-------------+
|            10 |     4400.00 |
|           ... |      .   .. |  -- 省略
|           110 |    12000.00 |
+---------------+-------------+
11 rows in set (0.00 sec)

-- 13.3 获取其中工资最低的信息:
mysql> SELECT department_id, MAX(salary) AS `max_salary` FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id
ORDER BY max_salary
LIMIT 1;
+---------------+------------+
| department_id | max_salary |
+---------------+------------+
|            10 |    4400.00 |
+---------------+------------+
1 row in set (0.00 sec)

-- 13.4 获取部门id:
mysql> SELECT department_id FROM (
    SELECT department_id, MAX(salary) AS `max_salary` FROM employees
    WHERE department_id IS NOT NULL
    GROUP BY department_id
    ORDER BY max_salary
    LIMIT 1
) AS `dep_id_table`;
+---------------+
| department_id |
+---------------+
|            10 |
+---------------+
1 row in set (0.00 sec)

-- 13.5 获取xx部门中的最低工资:
mysql> SELECT MIN(salary) AS `min_salary` FROM employees
WHERE department_id = (
    SELECT department_id FROM (
        SELECT department_id, MAX(salary) AS `max_salary` FROM employees
        WHERE department_id IS NOT NULL
        GROUP BY department_id
        ORDER BY max_salary
        LIMIT 1
    ) AS `dep_id_table`
);
+------------+
| min_salary |
+------------+
|    4400.00 |
+------------+
1 row in set (0.00 sec)

6.14 题14

-- 14. 查询平均工资最高的部门的manager的详细信息(员工id, 姓名, 邮箱, 薪资, 部门id): 
-- 14.1 查询部门的平均工资:
mysql> SELECT department_id, MAX(salary) FROM employees
GROUP BY department_id;
+---------------+-------------+
| department_id | MAX(salary) |
+---------------+-------------+
|          NULL |     7000.00 |
|            10 |     4400.00 |
|           ... |      .   .. |  -- 省略
|           110 |    12000.00 |
+---------------+-------------+
12 rows in set (0.00 sec)

-- 14.2 排除部门为NULL的信息:
mysql> SELECT department_id, MAX(salary) FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id;
+---------------+-------------+
| department_id | MAX(salary) |
+---------------+-------------+
|            10 |     4400.00 |
|           ... |      .   .. |  -- 省略
|           110 |    12000.00 |
+---------------+-------------+
11 rows in set (0.00 sec)

-- 14.3 获取其中工资最高的信息:
mysql> SELECT department_id, MAX(salary) AS `max_salary` FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id
ORDER BY max_salary DESC
LIMIT 1;
+---------------+------------+
| department_id | max_salary |
+---------------+------------+
|            90 |   24000.00 |
+---------------+------------+
1 row in set (0.00 sec)

-- 14.4 获取部门id:
mysql> SELECT department_id FROM (
    SELECT department_id, MAX(salary) AS `max_salary` FROM employees
    WHERE department_id IS NOT NULL
    GROUP BY department_id
    ORDER BY max_salary DESC
    LIMIT 1
) AS `dep_id_table`;
+---------------+
| department_id |
+---------------+
|            90 |
+---------------+
1 row in set (0.00 sec)

-- 14.5 通过部门id从部门表中获取管理者id:
mysql> SELECT manager_id FROM departments
WHERE department_id = (
    SELECT department_id FROM (
        SELECT department_id, MAX(salary) AS `max_salary` FROM employees
        WHERE department_id IS NOT NULL
        GROUP BY department_id
        ORDER BY max_salary DESC
        LIMIT 1
    ) AS `dep_id_table`
);
+------------+
| manager_id |
+------------+
|        100 |  -- 对应员工表中员工id
+------------+
1 row in set (0.00 sec)

-- 14.6 通过管理者id去员工表中获取管理者信息:
mysql> SELECT employee_id, first_name, email, salary, department_id FROM employees
WHERE employee_id = (
    SELECT manager_id FROM departments
    WHERE department_id = (
        SELECT department_id FROM (
            SELECT department_id, MAX(salary) AS `max_salary` FROM employees
            WHERE department_id IS NOT NULL
            GROUP BY department_id
            ORDER BY max_salary DESC
            LIMIT 1
        ) AS `dep_id_table`
    )
);
+-------------+------------+-------+----------+---------------+
| employee_id | first_name | email | salary   | department_id |
+-------------+------------+-------+----------+---------------+
|         100 | Steven     | SKING | 24000.00 |            90 |
+-------------+------------+-------+----------+---------------+
1 row in set (0.00 sec)

6.15 题15

-- 15. 查询部门的部门号, 其中不包括job_id是"ST_CLERK"的部门号:
-- 15.1 查询job_id是"ST_CLERK"的部门id:
mysql> SELECT department_id FROM employees
WHERE job_id = 'ST_CLERK';
+---------------+
| department_id |
+---------------+
|            50 |
|           ... |  -- 省略
|            50 |
+---------------+
20 rows in set (0.00 sec)

-- 15.3 查询部门表中不包含部门id不为xx的部门id:
mysql> SELECT department_id FROM departments
WHERE department_id NOT IN (
    SELECT  department_id FROM employees
    WHERE job_id = 'ST_CLERK'
);
+---------------+
| department_id |
+---------------+
|            10 |
|            20 |
|            30 |
|            40 |
|            60 |
|           ... |
+---------------+
26 rows in set (0.00 sec)

-- 使用departments表则为:
mysql> SELECT department_id FROM departments AS `main_dep`
WHERE NOT EXISTS (
    SELECT 1 FROM employees AS `sub_emp`
    WHERE job_id = 'ST_CLERK' 
    AND sub_emp.department_id = main_dep.department_id
);
+---------------+
| department_id |
+---------------+
|            10 |
|            20 |
|            30 |
|            40 |
|            60 |
|           ... |
+---------------+
26 rows in set (0.00 sec)

6.16 题16

-- 16. 选择所有没有管理者的员工的first_name:
-- 16.1 查询有管理者的员工:
mysql> SELECT first_name FROM employees
WHERE manager_id IN (  -- 员工拿着自己的管理者id去查自己是否有上级
    SELECT employee_id FROM employees  
);
+-------------+
| first_name  |
+-------------+
| Neena       |
| Lex         |
| ...         | -- 省略
| Hermann     |
| Shelley     |
| William     |
+-------------+
106 rows in set (0.00 sec)

-- 16.2 查询没有管理者的员工:
mysql> SELECT first_name FROM employees
WHERE manager_id NOT IN (  -- 员工拿着自己的管理者id去查自己是否有上级
    SELECT employee_id FROM employees ) 
OR manager_id IS NULL;  -- manager_id的值可以为NULL
+------------+
| first_name |
+------------+
| Steven     |
+------------+
1 row in set (0.00 sec)

-- 或:
mysql> SELECT first_name FROM employees AS `main_emp`
WHERE NOT EXISTS (  -- 排除有上级的员工
    SELECT 1 FROM employees AS `sub_emp`
    WHERE sub_emp.employee_id = main_emp.manager_id );  -- 员工拿着自己的管理者id去查自己是否有上级
+------------+
| first_name |
+------------+
| Steven     |
+------------+
1 row in set (0.00 sec)

6.17 题17

-- 17.查询员工号, 名字, 雇用时间, 工资, 其中员工的管理者为'Lex':
-- 17.1 查询的'Lex'的id:
mysql> SELECT employee_id FROM employees WHERE first_name = 'Lex';
+-------------+
| employee_id |
+-------------+
|         102 |
+-------------+
1 row in set (0.00 sec)

-- 17.2 查询员工的管理者id为102的信息:
mysql> SELECT employee_id, first_name, hire_date, salary FROM employees
WHERE manager_id  = (
    SELECT employee_id FROM employees WHERE first_name = 'Lex'
);
+-------------+------------+------------+---------+
| employee_id | first_name | hire_date  | salary  |
+-------------+------------+------------+---------+
|         103 | Alexander  | 1990-01-03 | 9000.00 |
+-------------+------------+------------+---------+
1 row in set (0.00 sec)

6.18 题18

-- 18. 查询各部门中工资比本部门平均工资高的员工的员工号, 名字和工资:
-- 18.1 使用相关子查询, 通过主查询提供的部门id计算部门的平均工资:
mysql> SELECT AVG(salary) FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_emp.department_id;

-- 18.2 查询工资大于自己部门平均工资的员工信息:
mysql> SELECT employee_id, first_name, salary FROM employees AS `main_emp`
WHERE salary > (
    SELECT AVG(salary) FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_emp.department_id
);
+-------------+------------+----------+
| employee_id | first_name | salary   |
+-------------+------------+----------+
|         100 | Steven     | 24000.00 |
|         103 | Alexander  |  9000.00 |
|         ... | ...        |      ... |  -- 省略
|         201 | Michael    | 13000.00 |
|         205 | Shelley    | 12000.00 |
+-------------+------------+----------+
38 rows in set (0.01 sec)

6.19 题19

-- 19. 查询每个部门下的部门人数大于 5 的部门名称:
-- 19.1 相关子查询, 通过主查询提供的部门id统计部门的人数:
mysql> SELECT COUNT(*) FROM employees AS `sub_emp`
WHERE sub_emp.department_id = main_emp.department_id;

-- 19.2 查询部门人数超过5的部门名称:
mysql> SELECT department_name FROM departments AS `main_emp`
WHERE 5 < (
    SELECT COUNT(*) FROM employees AS `sub_emp`
    WHERE sub_emp.department_id = main_emp.department_id
);
+-----------------+
| department_name |
+-----------------+
| Purchasing      |
| Shipping        |
| Sales           |
| Finance         |
+-----------------+
4 rows in set (0.00 sec)

6.20 题20

-- 20. 查询每个国家下的部门个数大于2的国家编号:
-- 地址表信息为: 位置ID, 街道地址, 邮政编码, 城市, 州/省和国家ID.

-- 20.1 统计位置相同的公司数量:
mysql> SELECT location_id, COUNT(*) AS `location_num` 
FROM departments
GROUP BY location_id;
+-------------+--------------+
| location_id | location_num |
+-------------+--------------+
|        1400 |            1 |
|        1500 |            1 |
|        1700 |           21 |
|        1800 |            1 |
|        2400 |            1 |
|        2500 |            1 |
|        2700 |            1 |
+-------------+--------------+
7 rows in set (0.00 sec)

-- 20.2 查询每个地区部门数大于2的国家编号:
mysql> SELECT location_id, COUNT(*) AS `location_num` 
FROM departments
GROUP BY location_id
HAVING location_num > 2;
+-------------+--------------+
| location_id | location_num |
+-------------+--------------+
|        1700 |           21 |
+-------------+--------------+
1 row in set (0.00 sec)

-- 20.3 获取地址id:
SELECT location_id FROM (
    SELECT location_id, COUNT(*) AS `location_num` 
    FROM departments
    GROUP BY location_id
    HAVING location_num > 2
) AS `location_num_table`;
+-------------+
| location_id |
+-------------+
|        1700 |
+-------------+
1 row in set (0.00 sec)

-- 20.4 通地址id去地址表中获取州/省和国家ID(country_id):
SELECT country_id FROM locations
WHERE location_id = (
    SELECT location_id FROM (
        SELECT location_id, COUNT(*) AS `location_num` 
        FROM departments
        GROUP BY location_id
        HAVING location_num > 2
    ) AS `location_num_table`
);
+------------+
| country_id |
+------------+
| US         |
+------------+
1 row in set (0.00 sec)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值