| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 20527 人关注过本帖
标题:[翻译]MySQL5.0用户手册——第三章:快速入门
只看楼主 加入收藏
京山游侠
Rank: 1
等 级:新手上路
帖 子:96
专家分:0
注 册:2006-2-12
收藏
得分:0 

3.3.4.7. 模式匹配

MySQL 提供标准的 SQL 模式匹配语法,同时也提供一种扩展的模式匹配语法,这种语法类似于在 Unix 中的 vi, grep, 和 sed工具中使用的正则表达式语法。

SQL 模式匹配允许你使用 ‘_’ 来匹配一个单个的字符和 ‘%’ 来匹配多个字符(包括0个字符)。在MySQL中,SQL 模式默认是不区分大小写的,下面是一些实例。请注意,你不能使用=<> 来进行 SQL 模式的比较,应该使用LIKENOT LIKE 比较符代替。

查找以 ‘b’开头的名字:

mysql> SELECT * FROM pet WHERE name LIKE 'b%';
+--------+--------+---------+------+------------+------------+
| name   | owner  | species | sex  | birth      | death      |
+--------+--------+---------+------+------------+------------+
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+

查找以 ‘fy’结尾的名字:

mysql> SELECT * FROM pet WHERE name LIKE '%fy';
+--------+--------+---------+------+------------+-------+
| name   | owner  | species | sex  | birth      | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  |
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |
+--------+--------+---------+------+------------+-------+

查找包含 ‘w’的名字:

mysql> SELECT * FROM pet WHERE name LIKE '%w%';
+----------+-------+---------+------+------------+------------+
| name     | owner | species | sex  | birth      | death      |
+----------+-------+---------+------+------------+------------+
| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       |
| Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |
+----------+-------+---------+------+------------+------------+

查找刚好是5个字符的名字, 可以使用五个 ‘_’ 模式字符:

mysql> SELECT * FROM pet WHERE name LIKE '_____';
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

MySQL提供的另外一种模式匹配 使用扩展的正则表达式, 当测试是否和这种模式相匹配时, 使用REGEXPNOT REGEXP 操作符 (或者RLIKENOT RLIKE)。

扩展正则表达式的一些通配符号如下:

  • .’ 匹配所有单个字符。

  • 一个字符集合 ‘[...]’ 匹配任何在这个集合中的字符。 例如, ‘[abc]’ 匹配 ‘a’, ‘b’, 或 ‘c’。 要指定一个范围的字符,可以使用一个破折号,如 ‘[a-z]’匹配所有字母, 而 ‘[0-9]’ 匹配所有数字。

  • *’ 匹配它前面的字符0到多遍, 例如,‘x*’匹配任意个 ‘x’ 字符, ‘[0-9]*’ 匹配任意位数的数字, ‘.*’ 匹配任意数量的任何字符。

  • 一个REGEXP 模式匹配操作只要字符串的匹配任何一处都算成功 。(这和LIKE 模式匹配不同,它只有当整个字符串都匹配的时候才算成功。)
  • 要指定一个模式必须和一个值的开头或结尾匹配,可在开头使用 ‘^’ 在结尾使用 ‘$’ 。

下面的例子把前面例子中语句重写,不使用LIKE而使用REGEXP,来展示正则表达式的功能:

查找以 ‘b’开头的名字, 使用 ‘^’ 来匹配名字的开头:

mysql> SELECT * FROM pet WHERE name REGEXP '^b';
+--------+--------+---------+------+------------+------------+
| name   | owner  | species | sex  | birth      | death      |
+--------+--------+---------+------+------------+------------+
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+

如果你确实想在进行REGEXP 比较时区分大小写, 可以使用BINARY 关键字让一个字符串成为二进制的字符串,这个查询配配以小写的 ‘b’ 开头的名字:

mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b';

查找以‘fy’结尾的名字,以 ‘$’ 来匹配名字的结尾:

mysql> SELECT * FROM pet WHERE name REGEXP 'fy$';
+--------+--------+---------+------+------------+-------+
| name   | owner  | species | sex  | birth      | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  |
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |
+--------+--------+---------+------+------------+-------+

查找包含 ‘w’的名字,使用如下查询:

mysql> SELECT * FROM pet WHERE name REGEXP 'w';
+----------+-------+---------+------+------------+------------+
| name     | owner | species | sex  | birth      | death      |
+----------+-------+---------+------+------------+------------+
| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       |
| Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |
+----------+-------+---------+------+------------+------------+

上面使用这则表达式匹配的例子和前面使用SQL模式匹配的例子不一样,因为正则表达式只要是在字符串中的任何地方匹配都算是跟整个字符串匹配,所以上面的例子不需要在'w'字符的两边加上通配符。

查找刚好只有五个字符的名字,使用 ‘^’ 和 ‘$’ 来匹配名字的开头和结尾,使用五个 ‘.’ 来匹配中间的值:

mysql> SELECT * FROM pet WHERE name REGEXP '^.....$';
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

你还可以使用{n} (“repeat-n-times”) 操作符来写上面的查询:

mysql> SELECT * FROM pet WHERE name REGEXP '^.{5}$';
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

Appendix G, MySQL Regular Expressions,提供了关于正则表达式符号的更多信息。


相濡以沫,不如相忘于江湖
2006-03-01 00:48
京山游侠
Rank: 1
等 级:新手上路
帖 子:96
专家分:0
注 册:2006-2-12
收藏
得分:0 

3.3.4.8. 行统计

数据库经常被用来回答这样的问题, “ 一个特定类型的数据在表中出现的频率如何?” 例如,你可能想知道你总共有多少只宠物, 或每一个主人拥有多少只宠物, 或者你想对你的宠物进行各种各样的统计。

你总共拥有多少只宠物等同于 “pet数据表里有多少行记录”, 因为每一只宠物的信息作为一行记录,COUNT(*) 统计行的总数,所以查找总共有多少宠物的语句如下:

mysql> SELECT COUNT(*) FROM pet;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+

以前,我们找出过宠物的主人有哪些,现在,你可以使用COUNT() 来找出每一个主人分别拥有几只宠物:

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Benny  |        2 |
| Diane  |        2 |
| Gwen   |        3 |
| Harold |        2 |
+--------+----------+

请注意GROUP BY 是用来把记录按照宠物的主人分组, 否则,你将得到一条错误信息:

mysql> SELECT owner, COUNT(*) FROM pet;
ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) 
with no GROUP columns is illegal if there is no GROUP BY clause

COUNT()GROUP BY 可以让你以各种各样的方式展示数据表中的数据,下面的例子显示了对pet表的各种统计操作:

按类别统计动物的数量:

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird    |        2 |
| cat     |        2 |
| dog     |        3 |
| hamster |        1 |
| snake   |        1 |
+---------+----------+

按性别统计动物的数量:

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
+------+----------+
| sex  | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+

(在这里,NULL表示不清楚动物的性别。)

按类别和性别统计动物的数量:

mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | NULL |        1 |
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

使用COUNT()时,你也不是一定要提取整个表的数据,例如,在前面的查询中,如果你只对猫和狗感兴趣,可以使用如下语句:

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE species = 'dog' OR species = 'cat'
    -> GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
+---------+------+----------+

如果你只想知道已知性别的动物的统计资料,如下:

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE sex IS NOT NULL
    -> GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

3.3.4.9. 使用多个表

pet表只是保存了你所拥有的宠物的基本信息,或许你还需要保存其它的信息,诸如象它们生活中发生的一些事件,比如什么时候看兽医了,什么时候生小动物了等等。这个表应该是个什么样子呢?它需要:

  • 需要包含宠物的名字,以便你能知道是发生在哪知宠物身上的事件。

  • 一个时间,以便你能知道事件是什么时候发生的。

  • 一个描述事件的字段。

  • 一个事件类型字段,以便你能将事件进行分类。

出于这些考虑,event表的CREATE TABLE 语句应该看起来象这样:

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
    -> type VARCHAR(15), remark VARCHAR(255));

pet 表一样,可以创建一个以tab符分割的文本文件来载入初始化数据:

name date type remark
Fluffy 1995-05-15 litter 4 kittens, 3 female, 1 male
Buffy 1993-06-23 litter 5 puppies, 2 female, 3 male
Buffy 1994-06-19 litter 3 puppies, 3 female
Chirpy 1999-03-21 vet needed beak straightened
Slim 1997-08-03 vet broken rib
Bowser 1991-10-12 kennel
Fang 1991-10-12 kennel
Fang 1998-08-28 birthday Gave him a new chew toy
Claws 1998-03-17 birthday Gave him a new flea collar
Whistler 1998-12-09 birthday First birthday

象这样载入记录:

mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;

以我们在pet 表上学到的查询基础,要在event表上执行查询是很简单的,因为它们的规则是一样的。 但是,如果event表自身的信息不足以回答你的问题,怎么办?

假设你想知道你的宠物是在多大年龄生小动物的,我们知道需要计算两个时间之间的差值,但是, 生小动物的时间在event 表种,但是要用来计算年龄的出生日期却在pet 表中,说明这个查询需要涉及到两个表:

mysql> SELECT pet.name,
    -> (YEAR(date)-YEAR(birth)) - (RIGHT(date,5)<RIGHT(birth,5)) AS age,
    -> remark
    -> FROM pet, event
    -> WHERE pet.name = event.name AND event.type = 'litter';
+--------+------+-----------------------------+
| name   | age  | remark                      |
+--------+------+-----------------------------+
| Fluffy |    2 | 4 kittens, 3 female, 1 male |
| Buffy  |    4 | 5 puppies, 2 female, 3 male |
| Buffy  |    5 | 3 puppies, 3 female         |
+--------+------+-----------------------------+

下面是这个查询中需要注意的事情:

  • FROM子句列出了两个表名,因为这个查询需要从两个表中提取数据。

  • 当关联 (joining) 多个表中的信息时, 你需要指定一个表中的信息是怎样和另外一个表中的信息进行匹配的,在这个例子中很简单,因为它们都有name字段, WHERE 子句使用name字段匹配两个表中的信息。

  • 由于name 列同时出现在两个表中, 所以你必须指定你引用的name列属于哪个表, 这是通过在列名前面指定表名来做到的。

你并不是必须在两个不同的表之间进行关联, 有些时候一个表也可以和它自己关联,如果你想在同一个表中把一条记录和另外一条记录进行比较,例如,要为两只动物配对,你可以让pet 表和自己关联来找出哪两只动物种类相同而性别不同:

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
    -> FROM pet AS p1, pet AS p2
    -> WHERE p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm';
+--------+------+--------+------+---------+
| name   | sex  | name   | sex  | species |
+--------+------+--------+------+---------+
| Fluffy | f    | Claws  | m    | cat     |
| Buffy  | f    | Fang   | m    | dog     |
| Buffy  | f    | Bowser | m    | dog     |
+--------+------+--------+------+---------+

在这个查询中,我们为这个表的两次引用分别指定了别名,这样可以明确指出哪个列名属于哪个引用。


相濡以沫,不如相忘于江湖
2006-03-02 16:10
京山游侠
Rank: 1
等 级:新手上路
帖 子:96
专家分:0
注 册:2006-2-12
收藏
得分:0 

3.4. 获得关于数据库和表格的信息

如果你忘记数据库或表的名字,或忘记一个给定表的结构 (例如,它的列叫什么名字),怎么办? MySQL 通过提供一些可以获取数据库和表的信息的语句来解决问题。

在前面我们看到过SHOW DATABASES语句, 该语句可以显示服务器上管理的所有数据库,如果要找出当前选择数据库,使用 DATABASE()函数:

mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie  |
+------------+

如果你没有选择任何数据库,则其结果为 NULL

要找出当前数据库中包含哪些表 (例如,你对某个表的名字不确定),使用如下命令:

mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| event               |
| pet                 |
+---------------------+

如果你想知道某一个表的结构,可以使用DESCRIBE 命令,它显示表格中每一列的信息。

mysql> DESCRIBE pet;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(20) | YES  |     | NULL    |       |
| owner   | varchar(20) | YES  |     | NULL    |       |
| species | varchar(20) | YES  |     | NULL    |       |
| sex     | char(1)     | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| death   | date        | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+

Field 是列的名称,Type 是列的数据类型, NULL 指出该列能否包含NULL 值,Key 指出该列是否作为索引, Default 指出该列的默认值。

如果你的表格有索引,SHOW INDEX FROM tbl_name 可以得到这些索引的信息。

3.5. 在批处理模式下使用mysql

在前面的章节中, 你以输入命令和显示结果的交互模式使用 mysql,你也可以让mysql 按批处理模式工作。 要以批处理的方式运行,你必须把你要执行的命令放入一个文件,然后告诉mysql 从这个文件读取命令。

shell> mysql < batch-file

如果是在Windows下运行mysql ,并且你的文件中包含一些可能引发问题的特殊字符, 你也可以这样使用:

C:\> mysql -e "source batch-file"

如果你必须在命令行指定连接参数,命令看起来应该是这样:

shell> mysql -h host -u user -p < batch-file
Enter password: ********

如果你以这种方式使用mysql ,你还可以创建一个脚本文件,然后运行这个脚本。

如果你希望你的脚本在执行的时候即使有些命令产生错误也不中断整个脚本的执行, 应该使用--force 命令行选项。

为什么要使用脚本呢?可能有以下理由:

  • 如果你经常需要重复执行一些查询 (比如说,每天或每星期),把它写成脚本可以避免每次执行时都要输入大量命令。

  • 你可以通过复制粘贴脚本文件中的部分内容来加速新的脚本的创建。

  • 批处理模式对于不断改进你的查询语句也很有帮助,特别是对于多行的命令或者多个语句的命令序列,如果语句中出现错误,你不用全部重新输入,只需要对脚本中的错误进行修改,然后让mysql 再执行它。

  • 如果你的查询有大量的输出, 你可以使用分页的方式来查看它,这比滚动屏幕的方式要好得多。

    shell> mysql < batch-file | more
    
  • 你可以把输出结果重定向到一个文件,以便进一步处理。

    shell> mysql < batch-file > mysql.out
    
  • 你可以将脚本文件发送给别人,让别人也能执行这些命令。

  • 有些情况下不允许交互式操作,例如,以cron job(类似计划任务)的方式执行查询,这种情况下,你就必须使用批处理模式。

批处理模式下默认的输出格式和交互模式有些不同 (更加简洁) 。例如,SELECT DISTINCT species FROM pet 在交互模式下的输出看起来如下:

+---------+
| species |
+---------+
| bird    |
| cat     |
| dog     |
| hamster |
| snake   |
+---------+

而在批处理模式下,看起来却是这样:

species
bird
cat
dog
hamster
snake

如果你希望在批处理模式下得到和交互模式相同的输出格式,请使用mysql -t。 如果要回显命令本身,请使用mysql -vvv

你还可以在mysql 提示符下面使用source 或者\. 命令来执行脚本文件:

mysql> source filename;
mysql> \. filename

相濡以沫,不如相忘于江湖
2006-03-02 20:43
京山游侠
Rank: 1
等 级:新手上路
帖 子:96
专家分:0
注 册:2006-2-12
收藏
得分:0 

3.6. 常用示例

这里是一些例子,可以演示怎样解决MySQL中的一些常见问题。

有些示例要使用shop 表,该表中保存有每一个商人的每种货物(使用编号保存)的价格,假设每一个商人的每一种物品具有单独的价格,则 (article, dealer) 是这个记录的主键。

启动命令行工具mysql 并且选择一个数据库:

shell> mysql your-database-name

(大多数情况下,你可以使用test数据库)。

可以这样创建这个示例数据表,并向其中装入数据:

mysql> CREATE TABLE shop (
    -> article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
    -> dealer  CHAR(20)                 DEFAULT ''     NOT NULL,
    -> price   DOUBLE(16,2)             DEFAULT '0.00' NOT NULL,
    -> PRIMARY KEY(article, dealer));
mysql> INSERT INTO shop VALUES
    -> (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
    -> (3,'C',1.69),(3,'D',1.25),(4,'D',19.95);

执行这两个语句后,表里面应该包含如下内容:

mysql> SELECT * FROM shop;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | A      |  3.45 |
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | B      |  1.45 |
|    0003 | C      |  1.69 |
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

3.6.1. 查询一列的最大值

“最大的商品编号是多少?”

SELECT MAX(article) AS article FROM shop;

+---------+
| article |
+---------+
|       4 |
+---------+

3.6.2. 查询一列的最大值所在的行的数据

任务:找出最贵的商品的编号、商人和价格。

利用一个嵌套查询,这很容易做到:

SELECT article, dealer, price
FROM   shop
WHERE  price=(SELECT MAX(price) FROM shop);

另一种做法是把表中的数据按 price进行降序排列, 然后使用 MySQL-特别提供的LIMIT 子句只提取第一行数据:

SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1;

Note: 如果表中具有多个最贵的商品, 每一个的价格都是 19.95,那么使用LIMIT 的方法就只能显示其中的一条信息。

3.6.3. 查询一列中每一组的最大值

任务:查找每一种商品的最高价格。

SELECT article, MAX(price) AS price
FROM   shop
GROUP BY article

+---------+-------+
| article | price |
+---------+-------+
|    0001 |  3.99 |
|    0002 | 10.99 |
|    0003 |  1.69 |
|    0004 | 19.95 |
+---------+-------+

3.6.4. 查询一列中每一组的最大值所在的行的数据

任务:对于每一种商品,查询最贵的那一个的编号、商人和价格信息。

这个问题可以用这样的嵌套查询解决:

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
              FROM shop s2
              WHERE s1.article = s2.article);

3.6.5. 使用自定义变量

你可以使用 MySQL 的自定义变量来储存查询结果,而不是一定要使用客户端的临时变量来存储查询结果。(请查看Section 9.3, “User-Defined Variables”.)

例如,要查找最贵和最便宜的商品,如下:

mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

相濡以沫,不如相忘于江湖
2006-03-03 23:57
xqiang
Rank: 1
等 级:新手上路
帖 子:291
专家分:0
注 册:2006-2-23
收藏
得分:0 
好,顶!
不好意思啊,现在才看到,呵呵!!!

相信自己可以的!!! http://www.
2006-03-04 09:33
xqiang
Rank: 1
等 级:新手上路
帖 子:291
专家分:0
注 册:2006-2-23
收藏
得分:0 
对了,京山兄,除了这个第三章,还有没有其他的学习MYSQL的文章啊?呵呵!!辛苦啦!

相信自己可以的!!! http://www.
2006-03-04 09:41
xqiang
Rank: 1
等 级:新手上路
帖 子:291
专家分:0
注 册:2006-2-23
收藏
得分:0 
大哥,3.8节怎么没有啊?

相信自己可以的!!! http://www.
2006-03-04 10:22
京山游侠
Rank: 1
等 级:新手上路
帖 子:96
专家分:0
注 册:2006-2-12
收藏
得分:0 
呵呵,还没有翻译完呢。请耐心等待哦。

按这样的速度,我想要把这个参考手册完全翻译完,大概需要一年的时间吧。

相濡以沫,不如相忘于江湖
2006-03-04 13:04
京山游侠
Rank: 1
等 级:新手上路
帖 子:96
专家分:0
注 册:2006-2-12
收藏
得分:0 

3.6.6. 使用外键

在MySQL中,InnoDB 表提供对外键约束的检查。请查看Section 14.2, “The InnoDB Storage Engine”, 和 Section 1.9.5.5, “Foreign Keys”.

如果只是连接两个表,外键不是必须的。对于InnoDB以外的其它数据库引擎,也可以使用REFERENCES tbl_name(col_name) 子句来定义一个列,但是不产生任何效果, 只是当成一个备注来提示你这个字段和另外一个表中的字段有联系, 在使用这个子句的时候,认识到以下几条是非常重要的:

  • MySQL 不进行任何类型的 CHECK 以确认col_name 列一定存在于tbl_name表中 (甚至是tbl_name 表自己是否存在)。

  • 当在一个外键所在的表中进行删除行之类的操作时,MySQL 不会在引用外键的表中进行任何动作, 换句话说,这个子句无论如何没有ON DELETEON UPDATE 动作的含义。 (即使你能在REFERENCES子句中写上ON DELETEON UPDATE 子句,它们也会被忽略。)

  • 该语句创建一个 ; 但是 创建任何类型的索引或键值。

  • 如果试图定义一个InnoDB 表,该语句将产生一个错误。

你可以创建一个和另外一个列有联系的列,如下:
CREATE TABLE person (
    id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    name CHAR(60) NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE shirt (
    id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
    color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
    owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),
    PRIMARY KEY (id)
);

INSERT INTO person VALUES (NULL, 'Antonio Paz');

SELECT @last := LAST_INSERT_ID();

INSERT INTO shirt VALUES
(NULL, 'polo', 'blue', @last),
(NULL, 'dress', 'white', @last),
(NULL, 't-shirt', 'blue', @last);

INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');

SELECT @last := LAST_INSERT_ID();

INSERT INTO shirt VALUES
(NULL, 'dress', 'orange', @last),
(NULL, 'polo', 'red', @last),
(NULL, 'dress', 'blue', @last),
(NULL, 't-shirt', 'white', @last);

SELECT * FROM person;
+----+---------------------+
| id | name                |
+----+---------------------+
|  1 | Antonio Paz         |
|  2 | Lilliana Angelovska |
+----+---------------------+

SELECT * FROM shirt;
+----+---------+--------+-------+
| id | style   | color  | owner |
+----+---------+--------+-------+
|  1 | polo    | blue   |     1 |
|  2 | dress   | white  |     1 |
|  3 | t-shirt | blue   |     1 |
|  4 | dress   | orange |     2 |
|  5 | polo    | red    |     2 |
|  6 | dress   | blue   |     2 |
|  7 | t-shirt | white  |     2 |
+----+---------+--------+-------+


SELECT s.* FROM person p, shirt s
 WHERE p.name LIKE 'Lilliana%'
   AND s.owner = p.id
   AND s.color <> 'white';

+----+-------+--------+-------+
| id | style | color  | owner |
+----+-------+--------+-------+
|  4 | dress | orange |     2 |
|  5 | polo  | red    |     2 |
|  6 | dress | blue   |     2 |
+----+-------+--------+-------+

在这种形式下,REFERENCES 并不在 SHOW CREATE TABLE 或者DESCRIBE语句的输出中显示:

SHOW CREATE TABLE shirt\G
*************************** 1. row ***************************
Table: shirt
Create Table: CREATE TABLE `shirt` (
`id` smallint(5) unsigned NOT NULL auto_increment,
`style` enum('t-shirt','polo','dress') NOT NULL,
`color` enum('red','blue','orange','white','black') NOT NULL,
`owner` smallint(5) unsigned NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

MyISAMBerkeleyDB 表中,这种方式使用的REFERENCES被当成一个注释或 “暗示” 。

3.6.7. 根据两个键查询

OR操作符对于使用一个键查询是最优化的, AND操作符也是如此。

一种特殊的情况是使用OR操作符来组合在两个键上的查询:

SELECT field1_index, field2_index FROM test_table
WHERE field1_index = '1' OR  field2_index = '1'

从MySQL 5.0.0版以后提供对这种情况的优化,请查看Section 7.2.6, “Index Merge Optimization”.

解决这个问题,还有一种有效率的办法,就是使用UNION 来联合两个 SELECT 语句的输出。请查看Section 13.2.7.2, “UNION Syntax”.

每一个SELECT 语句只从一个键查询,所有能够被优化:

SELECT field1_index, field2_index
    FROM test_table WHERE field1_index = '1'
UNION
SELECT field1_index, field2_index
    FROM test_table WHERE field2_index = '1';

3.6.8. 计算每天的访问量

下面的例子演示了怎样通过一组以bit开头的函数来计算一个月中用户有多少天访问了Web页:

CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL,
             day INT(2) UNSIGNED ZEROFILL);
INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),
            (2000,2,23),(2000,2,23);

示例表中包含了 year-month-day 数据以指示用户访问该Web页的时间, 要知道每个月有多少天有用户访问该Web页,使用如下语句:

SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1
       GROUP BY year,month;

返回结果如下:

+------+-------+------+
| year | month | days |
+------+-------+------+
| 2000 |    01 |    3 |
| 2000 |    02 |    2 |
+------+-------+------+

该查询计算每一个 year/month 组合中有多少不同的day, 重复的项将自动忽略。

3.6.9. 使用自动增量

AUTO_INCREMENT 属性可以用来自动为新增加的行产生唯一的标识。

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
 );

INSERT INTO animals (name) VALUES 
    ('dog'),('cat'),('penguin'),
    ('lax'),('whale'),('ostrich');

SELECT * FROM animals;

将返回:

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+

你可以通过LAST_INSERT_ID() SQL函数或者mysql_insert_id() C API 函数来获得最后一个 AUTO_INCREMENT 值。这些函数是独立于连接的,所以它们的返回值不会收到其它连接上插入的数据的影响。

注意: 对于多行的 insert语句,LAST_INSERT_ID()mysql_insert_id() 实际上返回这一次插入的第一行的AUTO_INCREMENT 键的值, 这允许多行插入能够在其它的replication服务器上正确的重现。

对于MyISAMBDB 表, 你可以指定多列索引中的第二列为AUTO_INCREMENT ,在这种情况下,AUTO_INCREMENT 列的值是通过 MAX(auto_increment_column) + 1 WHERE prefix=given-prefix计算的,当你想把数据放入有序群组的时候这是非常有用的。

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
);

INSERT INTO animals (grp,name) VALUES 
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;

将返回:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

请注意在这种情况下 (当AUTO_INCREMENT 列为多列索引的第二列的时候),当你删除了每一组中最大的 AUTO_INCREMENT 值之后,AUTO_INCREMENT 的值是可以重用的, 在 MyISAM 表中也是如此, 正常情况下AUTO_INCREMENT 值是不可重用的。

如果AUTO_INCREMENT 列是多列索引中的一列, MySQL 将使用该列来产生自动增量。 例如,如果animals 表中包含PRIMARY KEY (grp, id)INDEX (id),MySQL 将会忽略PRIMARY KEY 以产生自动增量序列,结果就是这个表中将只包含一个序列, 而不是每一个 grp 值都有一个单独的序列。

如果要让AUTO_INCREMENT 值不是从 1开始, 你可以使用 CREATE TABLEALTER TABLE来指定该值,例如:

mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;

关于AUTO_INCREMENT 的更多信息:


相濡以沫,不如相忘于江湖
2006-03-06 00:42
Knocker
Rank: 8Rank: 8
等 级:贵宾
威 望:47
帖 子:10454
专家分:603
注 册:2004-6-1
收藏
得分:0 

九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。     -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。   -毛泽东
2006-03-06 13:15
快速回复:[翻译]MySQL5.0用户手册——第三章:快速入门
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.014959 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved