SELECT prod_name FROM products LIMIT 5; # 返回前5行;类似 LIMIT 0,5 SELECT prod_name FROM products LIMIT 5, 10; # 返回从第5行(包括5)开始的10条数据; 注意下标从0开始。 SELECT prod_name FROM products LIMIT 10OFFSET5; # 返回从第5行开始的10行
ORDER BY
关系数据设计理论认为,如果不明确规定排序,则不应该假定检索出的数据的顺序有意义。
1 2 3 4 5 6 7 8
SELECT prod_name FROM products ORDERBY prod_name; SELECT prod_name FROM products ORDERBY prod_price; # 可以用非检索的列来排序 SELECT prod_name, prod_price FROM products ORDERBY prod_price,prod_name; # 多列检索 SELECT prod_name, prod_price FROM products ORDERBY prod_price,prod_name DESC; # 反序 (默认是ASC——升序) SELECT prod_name, prod_price FROM products ORDERBY prod_price DESC,prod_name; # 注意和上面的区别; SELECT prod_name, prod_price FROM products ORDERBY prod_price DESC,prod_name DESC; # DESC 关键字只应用到直接位于其前面的列名 SELECT prod_name, prod_price FROM products ORDERBY prod_price DESC LIMIT 1; # 找到最昂贵的物品; # ORDERBY 位于 FROM 之后,LIMIT 位于 ORDERBY 之后;
WHERE
1 2 3 4 5
SELECT prod_name, prod_price FROM products WHERE prod_price =2.50; SELECT prod_name, prod_price FROM products WHERE prod_price >=2.50; SELECT prod_name, prod_price FROM products WHERE prod_price BETWEEN5AND10; SELECT cust_id FROM customers WHERE cust_email ISNULL;
子句操作符
操作符
说明
=
等于
<>
不等于
!=
不等于
<
小于
<=
小于等于
>
大于
>=
大于等于
BETWEEN
在指定的两个值之间
AND & OR
1 2
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id =1003AND prod_price <=10; # 逻辑与 SELECT vend_id, prod_id, prod_price, prod_name FROM products WHERE vend_id =1003OR vend_id =1002; # 逻辑或
当AND和OR在一起时,在处理OR之前,优先处理AND操作符。解决办法是使用()
1 2 3
SELECT prod_name, prod_price FROM products WHERE vend_id =1002OR vend_id =1003AND prod_price >=10; SELECT prod_name, prod_price FROM products WHERE (vend_id =1002OR vend_id =1003) AND prod_price >=10; # 使用圆括号没有什么坏处,它能消除歧义
IN
1
SELECT prod_name,prod_price FROM products WHERE vend_id IN (1002, 1003) ORDERBY prod_name;
IN的功能与OR相当,且有更多的优点:
在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
在使用IN时,计算的次序更容易管理(因为使用的操作符更少)
IN操作符一般比OR操作符清单执行的更快。
IN的最大优点是可以包含其他SELECT语句,使得能够更容易动态地建立WHERE子句。
NOT,在WHERE子句中用来否定后跟条件的关键字
1
SELECT prod_name, prod_price FROM products WHERE vend_id NOTIN (1002, 1003) ORDERBY prod_name;
NOT可以和IN、BETWEEN、EXISTS子句结合使用,对结果取反。
通配符
1 2 3 4
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE'jet%'; # 检索任意以jet起头的词 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE'%anvil%'; # 检索任意位置包含文本anvil的值 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE'_ ton anvil'; # 与%可以匹配任意字符不一样, # _ 总是匹配一个字符,不能多也不能少
SELECT prod_name FROM products WHERE prod_name REGEXP '1000'ORDERBY prod_name; SELECT prod_name FROM products WHERE prod_name REGEXP '.000'ORDERBY prod_name; # `.`匹配任意一个字符 SELECT prod_name FROM products WHERE prod_name REGEXP BINARY'JetPack .000'; # 默认不匹配大小写, 使用 BINARY 来区分 SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000|3000'; # 进行OR匹配 SELECT prod_name FROM products WHERE prod_name REGEXP '[123] ton'; # 匹配任意几个字符, 指定一组用[和]括起来的字符 SELECT prod_name FROM products WHERE prod_name REGEXP '1|2|3 ton'; # 区别于上面的[123] ton,这里匹配的是1, 2, 3 ton SELECT prod_name FROM products WHERE prod_name REGEXP '[1-5] ton'; # 匹配范围 SELECT prod_name FROM products WHERE prod_name REGEXP '\\.'; # 匹配特殊字符, 需要使用转义符 # Mysql要求两个反斜杠(Mysql自己解释一个,正则表达式库解释一个) SELECT prod_name FROM products WHERE prod_name REGEXP '[:alnum:]'; # 匹配字符类,更多参考p58 SELECT prod_name FROM products WHERE prod_name REGEXP '\\([0-9] sticks?\\)'; # sticks? 匹配stick和sticks
重复元字符
元字符
说明
*
0 个或多个匹配
+
1 个或多个匹配(等于{1,})
?
0 个或 1 个匹配(等于{0,1})
{n}
指定数目的匹配
{n,}
不少于指定数目的匹配
{n,m}
匹配数目的范围(m 不超过 255)
定位元字符
元字符
说明
^
文本的开始
$
文本的结尾
[[:<:]]
词的开始
[[:>:]]
词的结尾
^ 有两种用法,在集合中(用[和]定义),用它来否定该集合,否则,用来指串的开始。
简单的正则表达示测试
1
SELECT'hello' REGEXP '[a-zA-Z]' # 验证字符是否符合正则
条件符合时结果为 1,条件不符合时结果为 0;
计算字段
1 2 3
SELECT Concat(vend_name, ' (', vend_country, ')') FROM vendors ORDERBY vend_name; # 拼接字段Concatenate, 将值连接到一起构成单个值 SELECT Concat(vend_name, ' (', vend_country, ')') AS vend_title FROM vendors ORDERBY vend_name; # 别名alias SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')') AS vend_title FROM vendors ORDERBY vend_name; # 去除左边LTrim(), 右边RTrim(), 两边Trim()的空格
MySQL 算术操作符
操作符
说明
+
加
-
减
*
乘
/
除
数据处理
1 2
SELECT vend_name, Upper(vend_name) AS vend_name_upcase FROM vendors ORDERBY vend_name; SELECT cust_name, cust_contact FROM customers WHERE Soundex(cust_contact) = Soundex('Y. Lie'); # 比较发音字符
常用文本处理函数
函数
说明
Left()
返回串左边的字符
Length()
返回串的长度
Locate()
找出串的一个子串
Lower()
将串转换为小写
LTrim()
去除串左边的空格
Right()
返回串右边的字符
RTrim()
去除串右边的空格
Soundex()
返回串的 SOUNDEX 值
SubString()
返回子串的字符
Upper()
将串转换为大写
1 2 3
SELECT cust_id, order_num FROM orders WHEREDate(order_date) ='2005-09-01'; SELECT cust_id, order_num FROM orders WHEREDate(order_date) BETWEEN'2005-09-01'AND'2005-09-30'; SELECT cust_id, order_num FROM orders WHEREYear(order_date) ='2005'ANDMonth(order_date) ='09';
常用日期和时间处理函数
函数
说明
AddDate()
增加一个日期(天、周等)
AddTime()
增加一个时间
CurDate()
返回当前日期
CurTime()
返回当前日间
Date()
返回日期时间的日期部分
DateDiff()
计算两个日期之差
Date_Add()
高度灵活的日期运算函数
Date_Format()
返回一个格式化的日期或时间串
Day()
返回一个日期的天数部分
DayOfWeek()
对于一个日期,返回对应的星期几
Hour()
返回一个时间的小时部分
Minute()
返回一个时间的分钟部分
Month()
返回一个日期的月数部分
Now()
返回当前日期和时间
Second()
返回一个时间的秒部分
Time()
返回一个日期的时间部分
Year()
返回一个日期的年份部分
汇总数据
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECTAVG(prod_price) AS avg_price FROM products; # AVG函数只作用于单个列,为了获得多个列的平均值,必须使用多个AVG函数 SELECTAVG(prod_price) AS avg_price FROM products WHERE vend_id=1003; # AVG 忽略列值为NULL的行 SELECTCOUNT(*) AS num_cust FROM customers; # 对表中的所有行计数, 不论是否为NULL SELECTCOUNT(cust_email) AS num_cust FROM customers; # 对特定的列计数,忽略NULL值 SELECTMAX(prod_price) AS max_price FROM products; # 找出最大值 ,忽略NULL值 SELECTMIN(prod_price) AS min_price FROM products; # 找出最小值 ,忽略NULL值 SELECTSUM(quantity) AS items_ordered FROM orderitems WHERE order_num =20005; # 指定列求和 SELECTSUM(quantity*item_price) AS total_price FROM orderitems WHERE order_num =20005; # 合计计算值 SELECTAVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id =1003; SELECTAVG(ALL prod_price) AS avg_price FROM products WHERE vend_id =1003; # 默认AVG(ALL) SELECTCOUNT(*) AS num_items, MIN(prod_price) AS price_min, MAX(prod_price) AS price_max, AVG(prod_price) AS price_avg FROM products;
SELECT vend_id, COUNT(*) AS num_prods FROM products GROUPBY vend_id; SELECT cust_id, COUNT(*) AS orders FROM orders GROUPBY cust_id HAVINGCOUNT(*) >=2; SELECT cust_id, COUNT(*) AS orders FROM orders GROUPBY cust_id HAVING orders >=2; # 第三条 SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >=10 GROUPBY vend_id HAVING num_prods >=2; # WHERE 和 HAVING 的区别, WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤, # WHERE 排除的行不包括在分组中 SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUPBY order_num HAVING ordertotal >=50; SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUPBY order_num HAVING ordertotal >=50ORDERBY ordertotal; # 对总计订单价格排序
SELECT cust_name, cust_contact FROM customers WHERE cust_id IN (SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id ='TNT2')); # 方法1 子查询 p92 SELECT cust_name, cust_contact FROM customers LEFTJOIN orders ON customers.cust_id = orders.cust_id LEFTJOIN orderitems ON orders.order_num = orderitems.order_num WHERE orderitems.prod_id ='TNT2'; # 方法2 外查询
SELECT cust_name, cust_state, (SELECTCOUNT(*) FROM orders WHERE orders.cust_id = customers.cust_id) AS orders FROM customers ORDERBY cust_name; # 有必要完全限定列名, 即: table名.filed名
SELECT cust_name, cust_contact FROM customers, orders, orderitems WHERE customers.cust_id = orders.cust_id AND orderitems.order_num = orders.order_num AND prod_id ='TNT2'; # 方法3 内部查询 p105
SELECT cust_name, cust_contact FROM customers INNERJOIN orders ON customers.cust_id = orders.cust_id INNERJOIN orderitems ON orders.order_num = orderitems.order_num WHERE orderitems.prod_id ='TNT2'; # 方法4 内部查询 INNERJOIN p104 # ANSI SQL 规范首选INNERJOIN 语法.对比WHERE子句,明确要使用联结条件, 性能更佳
SELECT p1.prod_id, p1.prod_name FROM products AS p1, products AS p2 WHERE p1.vend_id = p2.vend_id AND p2.prod_id ='DTNTR'; # 自联结 对比子查询, 有时候处理自联结远比处理子查询快的多
SELECT c.*, o.order_num, o.order_date, oi.prod_id, oi.quantity, oi.item_price FROM customers AS c, orders AS o, orderitems AS oi WHERE c.cust_id = o.cust_id AND oi.order_num = o.order_num AND prod_id ='FB'; # 自然联结 排除多次出现, 全每个列只返回一次 # 系统不完成这项工作, 由你自己完成它 # 一般是对表使用通配符 (SELECT*), 对所有其他表的列使用明确的子集来完成
SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <=5 UNION SELECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002);
SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <=5 UNIONALL SELECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002); # 使用 UNIONALL 不排除重复的行
SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <=5 UNION SELECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002) ORDERBY vend_id, prod_price; # 使用 UNION查询,只能使用一条ORDERBY 子句,必须出现在最后一条SELECT语句之后。但实际上是对所有结果排序。
UNION规则
UNION 必须由两条或两条以上的 SELECT 语句组成,语句之间用关键字 UNION 分隔(因此,如果组合 4 条 SELECT 语句,将要使用 3 个 UNION 关键字)
CREATEVIEW productcustomers AS SELECT cust_name, cust_contact, prod_id FROM customers, orders, orderitems WHERE customers.cust_id = orders.cust_id AND orderitems.order_num = orders.order_num; # 创建视图
SELECT cust_name, cust_contact FROM productcustomers WHERE prod_id ='TNT2'; # 查询视图
CREATEVIEW vendorlocations AS SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')') AS vend_title FROM vendors ORDERBY vend_name; # 创建重新格式化的视图
SELECT*FROM vendorlocations;
CREATEVIEW customeremaillist AS SELECT cust_id, cust_name, cust_email FROM customers WHERE cust_email ISNOTNULL; # 创建过滤条件的视图
SELECT*FROM customeremaillist;
CREATEVIEW orderitemsexpanded AS SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems; SELECT*FROM orderitemsexpanded WHERE order_num =20005;
CREATEPROCEDURE productpricing( OUT pl DECIMAL(8,2), OUT ph DECIMAL(8,2), OUT pa DECIMAL(8,2) ) BEGIN SELECTMin(prod_price) INTO pl FROM products; SELECTMAX(prod_price) INTO ph FROM products; SELECTAVG(prod_price) INTO pa FROM products; END; # 存储过程的创建 # 参数中的IN:传递数据给存储过程 # 参数中的OUT:从存储过程传出 # 参数中的INOUT:对存储过程传入传出
-- Name: order total -- Parameters: onumber = order number -- taxable = 0 if not taxable, 1 if taxable -- ototal = order total variable
CREATEPROCEDURE ordertotal( IN onumber INT, IN taxable BOOLEAN, OUT ototal DECIMAL(8, 2) ) COMMENT 'Obtain order total, optionally adding tax' BEGIN -- Declare variable for total DECLARE total DECIMAL(8, 2); -- Decliare tax percentage DECLARE taxrate INTDEFAULT6;
-- Get the order total SELECTSum(item_price*quantity) FROM orderitems WHERE order_num = onumber INTO total;
-- Is this taxable? IF taxable THEN # 不可使用 ELSEIF THEN、ELSE子句 SELECT total+(total/100*taxrate) INTO total; END IF;
-- And finally, save to out variable SELECT total INTO ototal; END;