MySQL必知必会2

使用数据处理函数


函数

与其他大多数计算机语言一样,SQL支持利用函数来处理数据。函数一般是在数据上执行的,他给数据的转换和处理提供了方便,在前一章中用来去掉尾空格的RTrim()就是一个函数的例子

文本处理函数

输入: SELECT vend_name,Upper(vend_name) AS vend_name_upcase FROM vendors ORDER BY vend_name;

分析: 将列 vend_name_upcase转换为大写

示例:

mysql> SELECT NAME,UPPER(NAME) AS name_upcase FROM account ORDER BY NAME;
+------+-------------+
| NAME | name_upcase |
+------+-------------+
| aaa  | AAA         |
| aest | AEST        |
| bbb  | BBB         |
| ccc  | CCC         |
| ccc  | CCC         |
| ddd  | DDD         |
| ddd  | DDD         |
| t57L | T57L        |
| test | TEST        |
| tsdf | TSDF        |
+------+-------------+

常用的文本处理函数

函数 说明
Left() 返回串左边的字符
Length() 返回串的长度
Locate() 找出串的一个子串
Lower() 将串转为小写
LTrim() 去掉串左边的空格
Right() 返回串右边的字符
RTrim() 去掉串右边的空格
Soundex() 返回串的SOUNDEX的值
SubString() 返回子串的字符
Upper() 将串转换为大写

日期和时间处理函数

日期和时间采用相应的数据类型和特殊的格式存储,以便于能快速和有效的排序或过滤,并且节省物理存储空间

常用日期和时间处理函数

函数 说明
AddDate() 增加一个日期(天、周等)
AddTime() 增加一个时间(时、分等)
CurDate() 返回当前日期
CurTime() 返回当前时间
Date() 返回日期时间的日期部分
DateDiff() 计算两个日期之差
Date_Add() 高度灵活的日期运算函数
Date_Format() 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
DayOfWeek() 对于一个日期、返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
Now() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分

汇总数据


聚集函数 运行在行组上,计算和返回单个值的函数

AVG函数

输入: SELECT AVG(prod_price) AS avg_price FROM products;

分析: 此SELECT语句返回值avg_price,它包含products表中所有产品的平均价格

只用于单个列 AVG()只能用来确定特定数值的平均值,而且列名必须作为函数参数给出

NULL值 AVG()函数忽略列值的NULL的行

COUNT函数

输入 SELECT COUNT(*) AS num_cust FROM customers;

分析 利用COUNT对所有行计数,不管行中各列有什么值。包含NULL值

输入 SELECT COUNT(cust_email) AS num_cust FROM customers;

分析 使用COUNT对cust_email列中有值的行进行计数,不包含NULL值

聚集不同的值

输入 SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id = 1003;

分析 排除掉相同的prod_price的值


分组数据


创建分组

输入 SELECT vend_id,COUNT(*) AS num_prods FROM proucts GROUP BY vend_id;

分析 上面的SELECT语句指定了两个列,vend_id包含产品供应商的ID,num_prods为计算字段。GROUP BY 子句指示MySQL按vendid排序并分组数据。

过滤分组

输入:

SELECT cust_id,COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2;

分析 HAVING子句,他过滤 count(*)>=2的那些分组

HAVING和WHERE的差别:HAVING用于分组后过滤,WHERE用于分组前过滤

分组和排序

输入

 SELECT order_num,SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >=50 ORDER BY ordertotal; 

输出

mysql>  SELECT order_num,SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >=50 ORDER BY ordertotal;
+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
|     20006 |      55.00 |
|     20008 |     125.00 |
|     20005 |     149.87 |
|     20007 |    1000.00 |
+-----------+------------+

使用子查询

利用子查询进行过滤

输入

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'
                                  )
                );

输出

+----------------+--------------+
| cust_name      | cust_contact |
+----------------+--------------+
| Coyote Inc.    | Y Lee        |
| Yosemite Place | Y Sam        |
+----------------+--------------+

分析

为了执行上述SELECT语句;MySQL实际上必须执行3条SELECT语句,最里边的子查询返回订单号列表,此列表用于其外面的子查询的WHERE子句。外面的子查询返回客户ID列表,此客户ID列表用于最外层的WHERE子句,最外层的查询确实返回所需的数据

连接表

外键

外键为某个表中的一列,他包含另一个表的主键值

创建联结

输入

SELECT vend_name,prod_name,prod_price
FROM vendors,products
WHERE vendors.vend_id=products.vend_id
ORDER BY vend_name,prod_name;

分析

最大的差别是在于所指定的两个列(prod_name和prod_price)在一个表中,二另一个列(vend_name)在另一个表中

现在来看FROM子句。与以前的SELECT语句不一样,这条语句的FROM子句列出了两个表,分别是vendors表和products表。他们就是这条SELECT语句联结的两个表的名字。这两个表用WHERE子句正确联结,WHER子句指示MySQL匹配vendors表中的vend_id和products表中的vend_id

*内部联结

输入

SELECT vend_name,prod_name,prod_price FROM vendors INNER JOIN products ON vendors.vend_id=products.vend_id;

分析 此语句中的SELECT域前面的SELECT语句相同,但FROM子句不同,这里,两个表之间的关系是FROM子句的组成部分,以INNER JOIN指定,在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出

创建高级联结

使用表别名

输入

SELECT cust_name,cust_contact
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='TNT2';

自联结

输入

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 customers.cust_id,orders.order_num
FORM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;

组合查询


多数SQL查询都只包含从一个或多个表中返回数据的单条SELECT语句。MySQL也允许执行多个查询(多条SELECT语句),并将结果作为单个查询结果集返回

创建组合查询

使用UNION

UNION的使用很简单。所需做的只是给出每条SELECT语句,在各条语句之间加上关键字UNION

输入

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)

分析 UNION指示MySQL执行两条语句,并把输出组合成单个查询结果集


全文本搜索


两个最常用的引擎为MyISAM和InnoDB,前者支持全文本搜索,后者不支持

使用全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断的重新索引

在对表列进行适当的设计后,MySQL会自动进行所有索引和重新索引

在索引之后,SELECT可与Match()和Against()一起使用以实际执行搜索

启用全文本搜索支持

一般在创建时启用全文本搜索,CREATE TABLE语句接收FULLTEXT子句,他给出被索引的一个逗号分隔的列表。

创建表

CREATE TABLE productnotes(
note_id INT NOT NULL AUTO_INCREMENT,
prod_id CHAR(10) NOT NULL,
note_date DATETIME NOT NULL,
note_text TEXT NULL,
PRIMARY KEY(note_id),
FULLTEXT(note_text)
)ENGINE=MYISAM;

分析 这些列中有一个名为note_text的列,为了进行全文本搜索,MySQL根据子句FULLTEXT(note_text)的指示对他进行索引。这里的FULLTEXT索引单个列,如果需要也可以指定多个列

在定义之后MySQL自动维护该索引,在增加、更新、或删除行时,索引随之自动更新

进行全文本搜索

在索引之后,使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表达式

输入

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against("rabbit");

分析 此SELECT语句检索单个列note_text。由于WHERE子句,一个全文本搜索被执行。Match(note_text)指示MySQL针对指定的列进行搜索,Against('rabbit')指定词rabbit作文搜索文本。

使用查询扩展

查询扩展用来设法放宽所返回的全文本搜索结果的范围,考虑下面的情况。你想找出所有提到anvils的注释。只有一个注释包含词anvils,但你还想找出可能与你的搜索有关的其他行,即使他们不包含词anvils

这也是扩展的一项任务,在使用查询扩展时,MySQL对数据和索引进行两遍扫描来完成搜索:

首先,进行一个基于全文本的搜索,找出与搜索条件匹配的所有行

其次,MySQL检查这些匹配并选择所有有用的词

在其次,MySQL再次进行全文搜索,这次不仅使用原来的条件,而且还使用所有有用的词

利用查询扩展,能找出可能相关的结果,即使他们并不精确包含所查找的词

使用查询扩展

SELECT note_text 
FROM productnotes
WHERE Match(note_text) Against('anvils' WITH QUERY EXPANSION);

布尔文本搜索

MySQL支持全文本搜索的另一种形式,称为布尔方式,即使没有全文本搜索也可以使用,但这是一种非常缓慢的操作

输入

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('heavy' IN BOOLEAN MODE);

分析 此全文本搜索检索包含词heavy的所有行,其中使用了关键字IN BOOLEAN MODE,但实际上没有指定布尔操作符,因此,其结果与没有指定布尔方式的结果相同

为了匹配包含heavy但不包含任意以rope开始的词的行可以使用以下查询
输入

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE);

全文本布尔操作符

布尔操作符 说明
+ 包含,词必须存在
- 排除,词必须不出现
> 包含,而且增加等级值
< 包含,且减少等级值
() 把词组成子表达式(允许这些子表达式作为一个组被包含、排除、排列等)
~ 取消一个词的排序值
* 词尾的通配符
"" 定义一个短语(与单个词的列表不一样,他匹配整个短语以便包含或排除这个短语)

插入数据


插入完整的行

输入

INSERT INTO customers(cust_name,
                      cust_contact,
                      cust_email,
                      cust_address,
                      cust_city,
                      cust_state

)VALUES('pEP e.lAPew',
        NULL,
        NULL,
        '100 Main Street',
        'los Angeles',
        'CA'
)

插入多个行

INSERT INTO customers(
    cust_name,
    cust_address,
    cust_city,
    cust_state,
    cust_zip,
    cust_country
)VALUES(
'Pep E. LaPew',
    '100 Main Street',
    'Los Angeles',
    'CA',
    '90046',
    'USA'
),
(
'M.Martian',
    '42 Galaxy Way',
    'New Your',
    'NY',
    '11213',
    'USA'
);

更新和删除数据


输入

UPDATE customers
SET cust_email='elmer@fudd.com'
WHERE cust_id=10005;

更新多个列

UPDATE customers
SET cust_name='The Fudds',
	cust_email='elmer@fudd.com'
WHERE cust_id=10005;

删除数据

DELETE FROM customers 
WHERE cust_id = 10006;
posted @ 2019-07-24 23:09  train99999  阅读(337)  评论(0编辑  收藏  举报