MySQL技巧汇总
本文我们来研究MySQL中一些对于WEB开发比较有实用价值的技巧:
1、两表内联接
在MySQL中对两个表作内联接有两种方式,一是在WHERE子句中针对一个叉积使用限制条件;二是在FROM子句中使用联接表达式。如下两个表格:
item表
| ID |
Name |
Price |
Description |
| 1 |
Toothbrush |
1.25 |
NULL |
| 2 |
Comb |
2.50 |
NULL |
| 3 |
Brush |
3.00 |
NULL |
| 4 |
Toothpaste |
0.75 |
NULL |
item_option表
| ID |
Item |
Name |
| 1 |
2 |
Red Plastic |
| 2 |
2 |
Blue Plastic |
其中item表的ID列与item_option表中的Item列相匹配,如果我们对两表作内联接查询,可以使用以下两种SQL语句
SELECT i.Name, i.Price, o.Name As 'Option
Name' FROM item i, item_option o WHERE i.ID = o.Item;
SELECT i.Name, i.Price, o.Name As 'Option Name' FROM item i INNER
JOIN item_option o ON i.ID = o.Item;
所返回的结果是一样的:
| Name |
Price |
Option Name |
| Comb |
2.50 |
Red Plastic |
| Comb |
2.50 |
Blue Plastic |
2、两表外联接
上例的查询结果只返回了"Comb"的列,这是因为在item_option表中只有Item=2(即Comb)的列,要获得所有商品的联接列表就需要使用外联接。MySQL允许左联接和右联接,但不支持完全外联接。本例的情况我们需要的是一个左联接:
SELECT i.Name, i.Price, o.Name As 'Option
Name' FROM item i LEFT JOIN item_option o ON i.ID = o.Item;
所得到的查询结果如下:
| Name |
Price |
Option Name |
| Toothbrush |
1.25 |
Null |
| Comb |
2.50 |
Red Plastic |
| Comb |
2.50 |
Red Plastic |
| Brush |
3.00 |
Null |
| Toothpaste |
0.75 |
Null |
3、GROUP BY分组子句
GROUP BY字句可以把结果集中具有不同特征的行聚集起来,比如上面的左联接例子,如果加上分组功能来统计不同的商品各自有多少种,可以用如下的SQL语句:
SELECT i.Name, i.Price, count(o.ID) As 'Options'
FROM item i LEFT JOIN item_option o ON i.ID = o.Item GROUP BY
i.Name ORDER BY Options;
结果如下:
| Name |
Price |
Options |
| Toothpaste |
0.75 |
0 |
| Toothbrush |
1.25 |
0 |
| Brush |
3.00 |
0 |
| Comb |
2.50 |
2 |
把这个例子引申开来,可以将很多复杂的问题简单化。比如站长以前工作时boss交下一个任务,为网站作一个记录搜索关键字的小程序,然后每周统计一次,报告的格式要求按照一段时间(即一周)内每个关键字被搜索的次数排序,目的是掌握哪些关键字被搜索的比较多,以便指导今后的关键字设置工作。
如果不使用GROUP BY的话,那么就只能把一段时间的记录都取出,然后循环一遍,用个数组记录,再把数组排下序得到结果。很显然这样的程序效率太差了。如果用GROUP
BY子句,就简单多了:
SELECT Keyword, count(Keyword) As 'Keycounts'
From keyrecord GROUP BY Keyword, ORDER BY Keycounts DESC;
结果基本如下:
| Keyword |
Keycounts |
| Women |
387 |
| Man |
312 |
| Person |
248 |
| World |
239 |
这样的查询结果就只需要直接显示就好了。
所以很多时候高效的SQL语句可以提高PHP脚本的效率。
4、WHERE子句中的逻辑和关系运算符
SELECT语句中的WHERE子句是一个非常重要的子句,它可以通过一系列逻辑和关系运算符来对查询作一定的限制以得到最准确的结果。比较常见的运算符有:
< 、 > 、 <= 、 >= 、 = 、 != 、 <> 、 IS NULL 等。比较特殊的一些运算符有:
<=> : 也是等于,但可以安全地同Null值比较,比如 NULL = NULL 会返回 NULL ,而 NULL
<=> NULL 则会返回 True
BETWEEN min AND max : 相当于 column >= min and column <=max
IN (...) : 在一个集合中
NOT IN (...) : 不在一个集合中
LIKE : 匹配一个模式,比如 column LIKE '%abc%'
NOT LIKE : 不匹配一个模式,比如已知某列有若干个模式,若想获得仅具有某模式的记录就可以通过用多个NOT LIKE来排除其它模式
IS NOT NULL : 非空值,一般否定运算符都是把 NOT 放在前面,只有 IS NULL 的否定形式是把 NOT 放中间的
5、MySQL的时间值
MySQL支持5种列类型来保存时间信息,其中 DATETIME 和 TIMESTAMP 是最有用的。它们的表示范围不同,DATETIME
的范围是从'1000-01-01 00:00:00'到'9999-12-31 23:59:59';而 TIMESTAMP 是从'1970-01-01
00:00:00'到'2037-12-31 23:59:59'
MySQL的时间类型是一个复合类型,即一系列整数值的集合,每一部分都有其自己的取值范围。其中月份限制在1~12之内,天数限制在1~31之内,小时限制在0~23之内,分钟和秒限制在0~59之内。如果在SQL语句中使用了不正确的时间值,那么就不会返回任何结果。因为MySQL不能防止无意义的日期。
MySQL允许使用部分日期,比如 1970-00-00可以表示1970年中月份和日期未知的一个日期。
在 WHERE 子句中使用时间值时有一些内部函数和运算方法可用,比如:
column < now() 表示字段值早于当前时间
column < now() - INTERVAL 15 MONTH 表示字段值早于15个月前
6、LAST_INSERT_ID
LAST_INSERT_ID([ID]) : 为每个连接保存的一个整数,以跟踪用于一个主键的最后一个整数。它可以返回一个值,如果提供一个值,就还可以设置那个值。
这个函数对于自增长列的及时返回有很重要的意义,比如站长作品中的几个网站都使用了一个信息记录可上传多个附件的功能,并且信息内容和多个附件是同时上传的,那么很明显,将信息内容插入到信息表格后,需要把该表格的自增长主键值返回以作为附件表格的外键插入值。在未了解
LAST_INSERT_ID 前也许我们会用:
SELECT ID From news ORDER BY ID DESC LIMIT
0,1;
来获取一个最大的ID。这个方法在多个连接同时往数据库表格里插入内容时是会出错的,比如在本连接插入一条信息之后马上有另一个连接也插入了一条信息,那么这个方法获取的ID就是错误的,除非你使用数据库锁定。但是锁定方法太复杂,而且在连接多的时候效率也不好。实际上我们只需要使用
select last_insert_id() 这样的语句即可获取正确的自增长值,因为这个函数是为每个连接都维持一个整数,所以是不会互相混淆的。
7、SQL语句中的算术函数
COUNT : 返回组内非 NULL 元素的数量;也可用count(*)来计算行数,无论它们是否为 NULL 。使用 count(DISTINCT
column) 可以计算在列上不重复的数量。
AVG : 返回组的平均值。
MIN MAX : 返回组内的最小值和最大值。
CEILING : 返回大于一个浮点数的最小的整数。
FLOOR : 返回小于一个浮点数的最大的整数。
ROUND : 将一个浮点数进位成整数,同 CEILING ,或在小数点后添加指定数量的数位,如 ROUND(15.666,2)=15.67
8、MySQL中的事务
MySQL中的事务由 Begin 开始,以 Commit 结束,如果要取消事务,可以用 Rollback