本文来自于《sql必知必会》
所需要的文件教程连接 本站其他的小伙伴
第一课 了解sql
数据库基础
什么是数据库
数据库(database) 保存有组织的数据的容器(通常是一个文 件或一组文件)。
表
表(table) 某种特定类型数据的结构化清单。
存储在表中的数据是一种类型的数据或一个 清单。决不应该将顾客的清单与订单的清单存储在同一个数据库表中。这 样做将使以后的检索和访问很困难。应该创建两个表,每个清单一个表。
表名的唯一性取决于多个因素,如数据库名和表名等的 结合。这表示,虽然在相同数据库中不能两次使用相同的表名, 但在不同的数据库中却可以使用相同的表名。
模式schema
模式(schema) 关于数据库和表的布局及特性的信息。
是模式还是数据库? 有时,模式用作数据库的同义词。遗憾 的是,模式的含义通常在上下文中并不是很清晰。
列和数据类型
列(column) 表中的一个字段。所有表都是由一个或多个列组 成的。
分解数据 正确地将数据分解为多个列极为重要。
数据类型(datatype) 所容许的数据的类型。每个表列都有相 应的数据类型,它限制(或容许)该列中存储的数据。
行
行(row) 表中的一个记录。
主键
主键(primary key)一一列(或一组列),其值能够唯一区分表 中每个行
唯一标识表中每行的这个列(或这组列)称为主键。主键用来表示 一个特定的行。没有主键,更新或删除表中特定行很困难,因为没有安 全的方法保证只涉及相关的行
应该总是定义主键 虽然并不总是都需要主键,但大多数数据 库设计人员都应保证他们创建的每个表具有一个主键,以便于 以后的数据操纵和管理
表中的任何列都可以作为主键,只要它满足以下条件:
-
任意两行都不具有相同的主键值;
-
每个行都必须具有一个主键值(主键列不允许NULL值)
主键的最好习惯 除MySQL强制实施的规则外,应该坚持的 几个普遍认可的最好习惯为:
- 不更新主键列中的值;
- 不重用主键列的值;
- 不在主键列中使用可能会更改的值。(例如,如果使用一个 名字作为主键以标识某个供应商,当该供应商合并和更改其 名字时,必须更改这个主键。
什么是sql
SQL(发音为字母S-Q-L或sequel)是结构化查询语言(Structured Query Language)的缩写。SQL是一种专门用来与数据库通信的语言
SQL有如下的优点。
- SQL不是某个特定数据库供应商专有的语言。几乎所有重要的 DBMS都支持SQL,所以,学习此语言使你几乎能与所有数据库 打交道。
- SQL简单易学。它的语句全都是由描述性很强的英语单词组成, 而且这些单词的数目不多。
- SQL尽管看上去很简单,但它实际上是一种强有力的语言,灵活 使用其语言元素,可以进行非常复杂和高级的数据库操作。
第二课 MySQL简述
什么是MySQL
数据的所有存储、 检索、管理和处理实际上是由数据库软件------DBMS(数据库管理系统) 完成的。MySQL是一种DBMS,即它是一种数据库软件。
为什么有那么多的公司和开发人员使用MySQL?
- 成本------MySQL是开放源代码的,一般可以免费使用(甚至可以 免费修改)。
- 性能------MySQL执行很快(非常快)。
- 可信赖------某些非常重要和声望很高的公司、站点使用MySQL, 这些公司和站点都用MySQL来处理自己的重要数据。
- 简单------MySQL很容易安装和使用。
客户机---服务器软件
DBMS可分为两类:一类为基于共享文件系统的DBMS,另一类为基 于客户机---服务器的DBMS。
前者(包括诸如Microsoft Access和FileMaker)用于桌面用途,通常不用于高端或更关键的应用。
MySQL、Oracle以及Microsoft SQL Server等数据库是基于客户机---服 务器的数据库。客户机---服务器应用分为两个不同的部分。服务器部分是 负责所有数据访问和处理的一个软件。这个软件运行在称为数据库服务 器的计算机上
第三课 检索数据
select语句
SQL语句是由简单的英语单词构成的。这些单词称 为关键字,每个SQL语句都是由一个或多个关键字构成的。大概,最经常 使用的SQL语句就是SELECT语句了。它的用途是从一个或多个表中检索 信息
关键字
作为 sql 组成部分的保留字。和其他语言一样关键字不能用作表或列名字。
检索单个列
sql
select prod_name from products;
#结构相当简单,从英文单词的语句就可以看出来从哪里选择。
+----------------+
| prod_name |
+----------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| Detonator |
| Bird seed |
| Carrots |
| Fuses |
| JetPack 1000 |
| JetPack 2000 |
| Oil can |
| Safe |
| Sling |
| TNT (1 stick) |
| TNT (5 sticks) |
+----------------+
当然也包括了相应的显示了多少行数据,以及花了多长时间
mysql
14 rows in set (0.00 sec)
当然上述数据可能没有排序,输出可能每个人也不一定相同
结束SQL语句 多条SQL语句必须以分号(;)分隔。MySQL 如同多数DBMS一样,不需要在单条SQL语句后加分号。但特 定的DBMS可能必须在单条SQL语句后加上分号。当然,如果 愿意可以总是加上分号。事实上,即使不一定需要,但加上 分号肯定没有坏处。如果你使用的是mysql命令行,必须加上 分号来结束SQL语句
MySQL没有大小写的区分许多SQL开发人员喜欢对所有SQL关键字使用大写,而对所有 列和表名使用小写,这样做使代码更易于阅读和调试
选择好自己的习惯
空格,和大多数其他语言一样空格通常也会被忽略掉SQL 语句可以在一行上给出,也可以分成许多行。多数SQL开发人 员认为将SQL语句分成多行更容易阅读和调试。
mysql
mysql> select prod_name
-> from Products;
+----------------+
| prod_name |
+----------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| Detonator |
| Bird seed |
| Carrots |
| Fuses |
| JetPack 1000 |
| JetPack 2000 |
| Oil can |
| Safe |
| Sling |
| TNT (1 stick) |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.00 sec)
mysql> select prod_name from Products;
+----------------+
| prod_name |
+----------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| Detonator |
| Bird seed |
| Carrots |
| Fuses |
| JetPack 1000 |
| JetPack 2000 |
| Oil can |
| Safe |
| Sling |
| TNT (1 stick) |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.00 sec)
mysql> select
-> prod_name
-> from
-> Products;
+----------------+
| prod_name |
+----------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| Detonator |
| Bird seed |
| Carrots |
| Fuses |
| JetPack 1000 |
| JetPack 2000 |
| Oil can |
| Safe |
| Sling |
| TNT (1 stick) |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.00 sec)
## 由此上述三种表述都是一样的效果
检索多个列
要想从一个表中检索多个列,使用相同的SELECT语句。唯一的不同 是必须在SELECT关键字后给出多个列名,列名之间必须以逗号分隔。
sql
mysql> select prod_id prod_name,prod_price
-> from Products;
+-----------+------------+
| prod_name | prod_price |
+-----------+------------+
| ANV01 | 5.99 |
| ANV02 | 9.99 |
| ANV03 | 14.99 |
| DTNTR | 13.00 |
| FB | 10.00 |
| FC | 2.50 |
| FU1 | 3.42 |
| JP1000 | 35.00 |
| JP2000 | 55.00 |
| OL1 | 8.99 |
| SAFE | 50.00 |
| SLING | 4.49 |
| TNT1 | 2.50 |
| TNT2 | 10.00 |
+-----------+------------+
14 rows in set (0.00 sec)
# 在这个例子中,指定了3个列名,列名之间用逗号分隔。
检索所有列
sql
mysql> select * from Products;
+---------+---------+----------------+------------+----------------------------------------------------------------+
| prod_id | vend_id | prod_name | prod_price | prod_desc
|
+---------+---------+----------------+------------+----------------------------------------------------------------+
| ANV01 | 1001 | .5 ton anvil | 5.99 | .5 ton anvil, black, complete with handy hook |
| ANV02 | 1001 | 1 ton anvil | 9.99 | 1 ton anvil, black, complete with handy hook and carrying case |
| ANV03 | 1001 | 2 ton anvil | 14.99 | 2 ton anvil, black, complete with handy hook and carrying case |
| DTNTR | 1003 | Detonator | 13.00 | Detonator (plunger powered), fuses not included |
| FB | 1003 | Bird seed | 10.00 | Large bag (suitable for road runners) |
| FC | 1003 | Carrots | 2.50 | Carrots (rabbit hunting season only) |
| FU1 | 1002 | Fuses | 3.42 | 1 dozen, extra long |
| JP1000 | 1005 | JetPack 1000 | 35.00 | JetPack 1000, intended for single use |
| JP2000 | 1005 | JetPack 2000 | 55.00 | JetPack 2000, multi-use |
| OL1 | 1002 | Oil can | 8.99 | Oil can, red
|
| SAFE | 1003 | Safe | 50.00 | Safe with combination lock |
| SLING | 1003 | Sling | 4.49 | Sling, one size fits all |
| TNT1 | 1003 | TNT (1 stick) | 2.50 | TNT, red, single stick |
| TNT2 | 1003 | TNT (5 sticks) | 10.00 | TNT, red, pack of 10 sticks |
+---------+---------+----------------+------------+----------------------------------------------------------------+
检索不同的值
mysql
mysql> select vend_id from Products;
+---------+
| vend_id |
+---------+
| 1001 |
| 1001 |
| 1001 |
| 1002 |
| 1002 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1005 |
| 1005 |
+---------+
14 rows in set (0.00 sec)
#不加限制就会产生重复数据(尽管并非无用),但是某些时候我们需要排除哪些重复
mysql> select distinct vend_id
-> from Products;
+---------+
| vend_id |
+---------+
| 1001 |
| 1002 |
| 1003 |
| 1005 |
+---------+
4 row# s in set (0.00 sec)
# distinct 显著的明显的缺失的
mysql> select distinct vend_id,prod_price from Products;
+---------+------------+
| vend_id | prod_price |
+---------+------------+
| 1001 | 5.99 |
| 1001 | 9.99 |
| 1001 | 14.99 |
| 1003 | 13.00 |
| 1003 | 10.00 |
| 1003 | 2.50 |
| 1002 | 3.42 |
| 1005 | 35.00 |
| 1005 | 55.00 |
| 1002 | 8.99 |
| 1003 | 50.00 |
| 1003 | 4.49 |
+---------+------------+
12 rows in set (0.01 sec)
# 两个组合效果
mysql> select vend_id,prod_price from Products;
+---------+------------+
| vend_id | prod_price |
+---------+------------+
| 1001 | 5.99 |
| 1001 | 9.99 |
| 1001 | 14.99 |
| 1003 | 13.00 |
| 1003 | 10.00 |
| 1003 | 2.50 |
| 1002 | 3.42 |
| 1005 | 35.00 |
| 1005 | 55.00 |
| 1002 | 8.99 |
| 1003 | 50.00 |
| 1003 | 4.49 |
| 1003 | 2.50 |
| 1003 | 10.00 |
+---------+------------+
14 rows in set (0.00 sec)
# 两个还是有显著不同的,
限制结果
MYSQL的关键字是limit,SQL server的关键字是top。
这里学的是mysql所以没有用sql server
sql
mysql> select prod_name from Products limit 5;
+--------------+
| prod_name |
+--------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| Detonator |
| Bird seed |
+--------------+
5 rows in set (0.00 sec)
## 这里是前5行
mysql> select prod_name from Products limit 5 offset 5;
+--------------+
| prod_name |
+--------------+
| Carrots |
| Fuses |
| JetPack 1000 |
| JetPack 2000 |
| Oil can |
+--------------+
5 rows in set (0.00 sec)
#这里是从第五行开始读5行,和其他语言一样都是从0开始计数
使用注释
随着数据的增长和数据库的庞大,sql的语句边长,复杂度也会变大,所以增加一些注释行会减少自己的维护成本。
sql
select prod_name from products; -- 这是注释
在 MySQL 中,有两种方式可以添加注释:
-
单行注释:使用
--
或#
开始一行文字,直到行尾都将被视为注释。例如:sqlSELECT * FROM table_name; -- 这是一条注释
-
多行注释:使用
/* */
将一段文字包裹起来作为注释。例如:sql/* 这是一个多行注释 可以在这里写很多内容 */
注释可以用于在 SQL 查询中解释代码的作用或者添加说明,但不会对查询结果产生任何影响。
- 编写SQL语句,从Customers表中检索所有的ID(cust_id)。
sql
SELECT cust_id
FROM Customers;
- OrderItems表包含了所有已订购的产品(有些已被订购多次)。编写SQL语句,检索并列出已订购产品(prod_id)的清单(不用列每个订单,只列出不同产品的清单)。
sql
SELECT DISTINCT prod_id
FROM OrderItems;
-
编写SQL语句,检索Customers表中所有的列,再编写另外的SELECT语句,仅检索顾客的ID。使用注释,注释掉一条SELECT语句,以便运行另一条SELECT语句。(当然,要测试这两个语句。)
SELECT *
SELECT cust_id
FROM Customers;
排序检索数据
第三课(补)排序数据
检索出的数据并不是以纯粹的随机顺序显示的。如果不排 序,数据一般将以它在底层表中出现的顺序显示。这可以是数据最初添加到表中的顺序。但是,如果数据后来进行过更新或删除,则此顺 序将会受到MySQL重用回收存储空间的影响。因此,如果不明确控 制的话,不能(也不应该)依赖该排序顺序。关系数据库设计理论认 为,如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有 意义
子句:SQL语句由子句构成,有些子句是必需的,而 有的是可选的。一个子句通常由一个关键字和所提供的数据组成。
sql
mysql> select prod_name from products order by prod_name;
+----------------+
| prod_name |
+----------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| Bird seed |
| Carrots |
| Detonator |
| Fuses |
| JetPack 1000 |
| JetPack 2000 |
| Oil can |
| Safe |
| Sling |
| TNT (1 stick) |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.00 sec)
按多个列排序
经常需要按不止一个列进行数据排序。为了按多个列排序,只要指定列名,列名之间用逗号分开即可(就 像选择多个列时所做的那样)
sql
mysql> select prod_id,prod_price,prod_name
-> from products
-> order by prod_price,prod_name;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| FC | 2.50 | Carrots |
| TNT1 | 2.50 | TNT (1 stick) |
| FU1 | 3.42 | Fuses |
| SLING | 4.49 | Sling |
| ANV01 | 5.99 | .5 ton anvil |
| OL1 | 8.99 | Oil can |
| ANV02 | 9.99 | 1 ton anvil |
| FB | 10.00 | Bird seed |
| TNT2 | 10.00 | TNT (5 sticks) |
| DTNTR | 13.00 | Detonator |
| ANV03 | 14.99 | 2 ton anvil |
| JP1000 | 35.00 | JetPack 1000 |
| SAFE | 50.00 | Safe |
| JP2000 | 55.00 | JetPack 2000 |
+---------+------------+----------------+
14 rows in set (0.00 sec)
order by 根据后面的顺序排序。
按列位置排序
sql
select prod_id, prod_price,prod_name from products;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| ANV01 | 5.99 | .5 ton anvil |
| ANV02 | 9.99 | 1 ton anvil |
| ANV03 | 14.99 | 2 ton anvil |
| DTNTR | 13.00 | Detonator |
| FB | 10.00 | Bird seed |
| FC | 2.50 | Carrots |
| FU1 | 3.42 | Fuses |
| JP1000 | 35.00 | JetPack 1000 |
| JP2000 | 55.00 | JetPack 2000 |
| OL1 | 8.99 | Oil can |
| SAFE | 50.00 | Safe |
| SLING | 4.49 | Sling |
| TNT1 | 2.50 | TNT (1 stick) |
| TNT2 | 10.00 | TNT (5 sticks) |
+---------+------------+----------------+
14 rows in set (0.00 sec)
# 有上图知道是第2 3列
mysql> select prod_id, prod_price,prod_name
-> from products
-> order by 2,3;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| FC | 2.50 | Carrots |
| TNT1 | 2.50 | TNT (1 stick) |
| FU1 | 3.42 | Fuses |
| SLING | 4.49 | Sling |
| ANV01 | 5.99 | .5 ton anvil |
| OL1 | 8.99 | Oil can |
| ANV02 | 9.99 | 1 ton anvil |
| FB | 10.00 | Bird seed |
| TNT2 | 10.00 | TNT (5 sticks) |
| DTNTR | 13.00 | Detonator |
| ANV03 | 14.99 | 2 ton anvil |
| JP1000 | 35.00 | JetPack 1000 |
| SAFE | 50.00 | Safe |
| JP2000 | 55.00 | JetPack 2000 |
+---------+------------+----------------+
14 rows in set (0.00 sec)
指定排序方向
数据排序不限于升序排序(从A到Z)。这只是默认的排序顺序,还可 以使用ORDER BY子句以降序(从Z到A)顺序排序。为了进行降序排序, 必须指定DESC关键字。
sql
mysql> select prod_id,prod_price,prod_name
-> from products
-> order by prod_price desc;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| JP2000 | 55.00 | JetPack 2000 |
| SAFE | 50.00 | Safe |
| JP1000 | 35.00 | JetPack 1000 |
| ANV03 | 14.99 | 2 ton anvil |
| DTNTR | 13.00 | Detonator |
| FB | 10.00 | Bird seed |
| TNT2 | 10.00 | TNT (5 sticks) |
| ANV02 | 9.99 | 1 ton anvil |
| OL1 | 8.99 | Oil can |
| ANV01 | 5.99 | .5 ton anvil |
| SLING | 4.49 | Sling |
| FU1 | 3.42 | Fuses |
| FC | 2.50 | Carrots |
| TNT1 | 2.50 | TNT (1 stick) |
+---------+------------+----------------+
14 rows in set (0.00 sec)
sql
mysql> select prod_id,prod_price,prod_name
-> from products
-> order by prod_price desc,prod_name;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| JP2000 | 55.00 | JetPack 2000 |
| SAFE | 50.00 | Safe |
| JP1000 | 35.00 | JetPack 1000 |
| ANV03 | 14.99 | 2 ton anvil |
| DTNTR | 13.00 | Detonator |
| FB | 10.00 | Bird seed |
| TNT2 | 10.00 | TNT (5 sticks) |
| ANV02 | 9.99 | 1 ton anvil |
| OL1 | 8.99 | Oil can |
| ANV01 | 5.99 | .5 ton anvil |
| SLING | 4.49 | Sling |
| FU1 | 3.42 | Fuses |
| FC | 2.50 | Carrots |
| TNT1 | 2.50 | TNT (1 stick) |
+---------+------------+----------------+
14 rows in set (0.00 sec)
DESC关键字只应用到直接位于其前面的列名。在上例中,只对 prod_price列指定DESC,对prod_name列不指定。因此, prod_price列以降序排序,而prod_name列(在每个价格内)仍然按标准 的升序排
在多个列上降序排序 如果想在多个列上进行降序排序,必须 对每个列指定DESC关键字。
区分大小写和排序顺序 在对文本性的数据进行排序时,A与 a相同吗?a位于B之前还是位于Z之后?这些问题不是理论问 题,其答案取决于数据库如何设置。在字典(dictionary)排序顺序中,A被视为与a相同,这是MySQL (和大多数数据库管理系统)的默认行为。但是,许多数据库 管理员能够在需要时改变这种行为(如果你的数据库包含大量 外语字符,可能必须这样做)
sql
-- prod_price DESC保证行是按照由最昂贵到最便宜检索的,而LIMIT 1告诉MySQL仅返回一行。
mysql> select prod_price
-> from products
-> order by prod_price desc
-> limit 1;
+------------+
| prod_price |
+------------+
| 55.00 |
+------------+
1 row in set (0.00 sec)
1.编写SQL语句,从Customers中检索所有的顾客名称(cust_names),并按从Z到A的顺序显示结果。
sql
mysql> SELECT cust_name
-> FROM Customers
-> ORDER BY cust_name DESC;
+----------------+
| cust_name |
+----------------+
| Yosemite Place |
| Wascals |
| Mouse House |
| E Fudd |
| Coyote Inc. |
+----------------+
5 rows in set (0.00 sec)
2.编写SQL语句,从Orders表中检索顾客ID(cust_id)和订单号(order_num),并先按顾客ID对结果进行排序,再按订单日期倒序排列。
sql
SELECT cust_id, order_num
FROM Orders
ORDER BY cust_id, order_date DESC;
--------------------
mysql> SELECT cust_id, order_num
-> FROM Orders
-> ORDER BY cust_id, order_date DESC;
+---------+-----------+
| cust_id | order_num |
+---------+-----------+
| 10001 | 20009 |
| 10001 | 20005 |
| 10003 | 20006 |
| 10004 | 20007 |
| 10005 | 20008 |
+---------+-----------+
5 rows in set (0.00 sec)
3.显然,我们的虚拟商店更喜欢出售比较贵的物品,而且这类物品有很多。编写SQL语句,显示OrderItems表中的数量和价格(item_price),并按数量由多到少、价格由高到低排序。
sql
SELECT quantity, item_price
FROM OrderItems
ORDER BY quantity DESC, item_price DESC;
---------------------------------------
mysql> select quantity,item_price
-> from orderItems
-> order by quantity desc,item_price desc;
+----------+------------+
| quantity | item_price |
+----------+------------+
| 100 | 10.00 |
| 50 | 2.50 |
| 10 | 5.99 |
| 5 | 10.00 |
| 3 | 9.99 |
| 1 | 55.00 |
| 1 | 14.99 |
| 1 | 10.00 |
| 1 | 10.00 |
| 1 | 8.99 |
| 1 | 4.49 |
+----------+------------+
11 rows in set (0.00 sec)
4.下面的SQL语句有问题吗?(尝试在不运行的情况下指出。)
sql
SELECT vend_name,
FROM Vendors
ORDER vend_name DESC;
#多了个逗号。
第四课 过滤数据
使用where子句
数据库表一般包含大量的数据,很少需要检索表中所有行。通常只 会根据特定操作或报告的需要提取表数据的子集。只检索所需数据需要 指定搜索条件(search criteria),搜索条件也称为过滤条件(filter condition)。
sql
mysql> select prod_name, prod_price
-> from products
-> where prod_price = 2.5;
+---------------+------------+
| prod_name | prod_price |
+---------------+------------+
| Carrots | 2.50 |
| TNT (1 stick) | 2.50 |
+---------------+------------+
2 rows in set (0.00 sec)
SQL过滤与应用过滤 数据也可以在应用层过滤。为此目 的,SQL的SELECT语句为客户机应用检索出超过实际所需的 数据,然后客户机代码对返回数据进行循环,以提取出需要 的行
WHERE子句的位置 在同时使用ORDER BY和WHERE子句时,应 该让ORDER BY位于WHERE之后,否则将会产生错误.
where 子句操作符
操作符 | 描述 |
---|---|
= | 等于 |
!= 或 <> | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
BETWEEN | 在指定范围内 |
LIKE | 匹配模式 |
IN | 在指定值列表中 |
IS NULL | 为空值 |
IS NOT NULL | 不为空值 |
检查单个值
sql
mysql> select prod_name,prod_price
-> from products
-> where prod_price <10;
+---------------+------------+
| prod_name | prod_price |
+---------------+------------+
| .5 ton anvil | 5.99 |
| 1 ton anvil | 9.99 |
| Carrots | 2.50 |
| Fuses | 3.42 |
| Oil can | 8.99 |
| Sling | 4.49 |
| TNT (1 stick) | 2.50 |
+---------------+------------+
7 rows in set (0.00 sec)
+++++++++++++++++++++++++++++++++++
mysql> select prod_name,prod_price
-> from products
-> where prod_price <= 10;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| .5 ton anvil | 5.99 |
| 1 ton anvil | 9.99 |
| Bird seed | 10.00 |
| Carrots | 2.50 |
| Fuses | 3.42 |
| Oil can | 8.99 |
| Sling | 4.49 |
| TNT (1 stick) | 2.50 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
9 rows in set (0.00 sec)
不匹配检查
sql
mysql> select vend_id ,prod_name
-> from products
-> where vend_id <> 1003;
+---------+--------------+
| vend_id | prod_name |
+---------+--------------+
| 1001 | .5 ton anvil |
| 1001 | 1 ton anvil |
| 1001 | 2 ton anvil |
| 1002 | Fuses |
| 1002 | Oil can |
| 1005 | JetPack 1000 |
| 1005 | JetPack 2000 |
+---------+--------------+
7 rows in set (0.01 sec)
sql
mysql> select vend_id ,prod_name
-> from products
-> where vend_id != 1003;
+---------+--------------+
| vend_id | prod_name |
+---------+--------------+
| 1001 | .5 ton anvil |
| 1001 | 1 ton anvil |
| 1001 | 2 ton anvil |
| 1002 | Fuses |
| 1002 | Oil can |
| 1005 | JetPack 1000 |
| 1005 | JetPack 2000 |
+---------+--------------+
7 rows in set (0.01 sec)
范围值检查
sql
mysql> select prod_name,prod_price
-> from products
-> where prod_price between 5 and 10;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| .5 ton anvil | 5.99 |
| 1 ton anvil | 9.99 |
| Bird seed | 10.00 |
| Oil can | 8.99 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
5 rows in set (0.00 sec)
在使用BETWEEN时,必须指定两个值 ------所需范围的低端值和高端值。这两个值必须用AND关键字 分隔。BETWEEN匹配范围中所有的值,包括指定的开始值和结束值。
空值检查
在创建表时,表设计人员可以指定其中的列是否可以不包含值。在 一个列不包含值时,称其为包含空值NULL。
NULL 无值(no value),它与字段包含0、空字符串或仅仅包含 空格不同
sql
mysql> select cust_name
-> from customers
-> where cust_email is null;
+-------------+
| cust_name |
+-------------+
| Mouse House |
| E Fudd |
+-------------+
2 rows in set (0.00 sec)
NULL与不匹配 在通过过滤选择出不具有特定值的行时,你 可能希望返回具有NULL值的行。但是,不行。因为未知具有 特殊的含义,数据库不知道它们是否匹配,所以在匹配过滤 或不匹配过滤时不返回它们。 因此,在过滤数据时,一定要验证返回数据中确实给出了被 过滤列具有NULL的行。
1.编写SQL语句,从Products表中检索产品ID(prod_id)和产品名称(prod_name),只返回价格为9.49美元的产品。
sql
mysql> SELECT prod_id, prod_name
-> FROM Products
-> WHERE prod_price = 9.49;
Empty set (0.00 sec)
2.编写SQL语句,从Products表中检索产品ID(prod_id)和产品名称(prod_name),只返回价格为9美元或更高的产品。
sql
mysql> SELECT prod_id, prod_name
-> FROM Products
-> WHERE prod_price >= 9;
+---------+----------------+
| prod_id | prod_name |
+---------+----------------+
| ANV02 | 1 ton anvil |
| ANV03 | 2 ton anvil |
| DTNTR | Detonator |
| FB | Bird seed |
| JP1000 | JetPack 1000 |
| JP2000 | JetPack 2000 |
| SAFE | Safe |
| TNT2 | TNT (5 sticks) |
+---------+----------------+
8 rows in set (0.00 sec)
3.结合第3课和第4课编写SQL语句,从OrderItems表中检索出所有不同订单号(order_num),其中包含100个或更多的产品。
sql
mysql> SELECT DISTINCT order_num
-> FROM OrderItems
-> WHERE quantity >=100;
+-----------+
| order_num |
+-----------+
| 20007 |
+-----------+
1 row in set (0.00 sec)
4.编写SQL语句,返回Products表中所有价格在3美元到6美元之间的产品的名称(prod_name)和价格(prod_price),然后按价格对结果进行排序。(本题有多种解决方案,我们在下一课再讨论,不过你可以使用目前已学的知识来解决它。)
sql
mysql> SELECT prod_name, prod_price
-> FROM products
-> WHERE prod_price BETWEEN 3 AND 6
-> ORDER BY prod_price;
+--------------+------------+
| prod_name | prod_price |
+--------------+------------+
| Fuses | 3.42 |
| Sling | 4.49 |
| .5 ton anvil | 5.99 |
+--------------+------------+
3 rows in set (0.00 sec)
第五课 数据过滤
组合where子句
and操作符
为了进行更强的过滤控制,MySQL允许给出多个WHERE子句。这些子 句可以两种方式使用:以AND子句的方式或OR子句的方式使用。
sql
mysql> select prod_id,prod_price,prod_name
-> from products
-> where vend_id = 1003 and prod_price <=10;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| FB | 10.00 | Bird seed |
| FC | 2.50 | Carrots |
| SLING | 4.49 | Sling |
| TNT1 | 2.50 | TNT (1 stick) |
| TNT2 | 10.00 | TNT (5 sticks) |
+---------+------------+----------------+
5 rows in set (0.00 sec)
or操作符
sql
mysql> select prod_name ,prod_price
-> from products
-> where vend_id =1002 or vend_id =1003;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| Fuses | 3.42 |
| Oil can | 8.99 |
| Detonator | 13.00 |
| Bird seed | 10.00 |
| Carrots | 2.50 |
| Safe | 50.00 |
| Sling | 4.49 |
| TNT (1 stick) | 2.50 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
9 rows in set (0.00 sec)
计算次序
WHERE可包含任意数目的AND和OR操作符。允许两者结合以进行复杂 和高级的过滤
sql
mysql> select prod_name,prod_price
-> from products
-> where prod_id = 1002 or vend_id = 1003 and prod_price >=10;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| Detonator | 13.00 |
| Bird seed | 10.00 |
| Safe | 50.00 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
4 rows in set, 14 warnings (0.00 sec)
由于AND在计算次序中优先级更高,操作 符被错误地组合了
sql
mysql> select prod_name,prod_price
-> from products
-> where (prod_id = 1002 or vend_id =1003)and prod_price >=10;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| Detonator | 13.00 |
| Bird seed | 10.00 |
| Safe | 50.00 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
4 rows in set, 14 warnings (0.00 sec)
# 这里可以看出优先级的差距
在WHERE子句中使用圆括号 任何时候使用具有AND和OR操作 符的WHERE子句,都应该使用圆括号明确地分组操作符。不要 过分依赖默认计算次序,即使它确实是你想要的东西也是如 此。使用圆括号没有什么坏处,它能消除歧义
in操作符
圆括号在WHERE子句中还有另外一种用法。IN操作符用来指定条件范 围,范围中的每个条件都可以进行匹配。IN取合法值的由逗号分隔的清 单,全都括在圆括号中。
sql
mysql> select prod_name,prod_price
-> from products
-> where vend_id in (1002,1003)
-> order by prod_name;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| Bird seed | 10.00 |
| Carrots | 2.50 |
| Detonator | 13.00 |
| Fuses | 3.42 |
| Oil can | 8.99 |
| Safe | 50.00 |
| Sling | 4.49 |
| TNT (1 stick) | 2.50 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
9 rows in set (0.00 sec)
sql
--下面实现的效果和上面的一样
mysql> select prod_name ,prod_price
-> from products
-> where vend_id = 1002 or 1003
-> order by prod_name;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| .5 ton anvil | 5.99 |
| 1 ton anvil | 9.99 |
| 2 ton anvil | 14.99 |
| Bird seed | 10.00 |
| Carrots | 2.50 |
| Detonator | 13.00 |
| Fuses | 3.42 |
| JetPack 1000 | 35.00 |
| JetPack 2000 | 55.00 |
| Oil can | 8.99 |
| Safe | 50.00 |
| Sling | 4.49 |
| TNT (1 stick) | 2.50 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
14 rows in set (0.00 sec)
为什么要使用IN操作符?其优点具体如下。
- 在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
- 在使用IN时,计算的次序更容易管理(因为使用的操作符更少)。
- IN操作符一般比OR操作符清单执行更快。
- IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建 立WHERE子句。第14章将对此进行详细介绍
not的加入
sql
mysql> select prod_name ,prod_price
-> from products
-> where vend_id not in (1002,1003)
-> order by prod_name;
+--------------+------------+
| prod_name | prod_price |
+--------------+------------+
| .5 ton anvil | 5.99 |
| 1 ton anvil | 9.99 |
| 2 ton anvil | 14.99 |
| JetPack 1000 | 35.00 |
| JetPack 2000 | 55.00 |
+--------------+------------+
5 rows in set (0.00 sec)
1.编写SQL语句,从Vendors表中检索供应商名称(vend_name),仅返回加利福尼亚州的供应商(这需要按国家[USA]和州[CA]进行过滤,没准其他国家也存在一个加利福尼亚州)。提示:过滤器需要匹配字符串。
sql
mysql> SELECT vend_name
-> FROM Vendors
-> WHERE vend_country = 'USA' AND vend_state = 'CA';
+-----------+
| vend_name |
+-----------+
| ACME |
+-----------+
1 row in set (0.00 sec)
2.编写SQL语句,查找所有至少订购了总量100个的BR01、BR02或BR03的订单。你需要返回OrderItems表的订单号(order_num)、产品ID(prod_id)和数量,并按产品ID和数量进行过滤。提示:根据编写过滤器的方式,可能需要特别注意求值顺序。
sql
mysql> SELECT order_num, prod_id, quantity
-> FROM OrderItems
-> WHERE prod_id IN ('BR01','BR02','BR03')
-> AND quantity >=100;
Empty set (0.00 sec)
3.现在,我们回顾上一课的挑战题。编写SQL语句,返回所有价格在3美元到6美元之间的产品的名称(prod_name)和价格(prod_price)。使用AND,然后按价格对结果进行排序。
sql
mysql> SELECT prod_name, prod_price
-> FROM products
-> WHERE prod_price >= 3 AND prod_price <= 6
-> ORDER BY prod_price;
+--------------+------------+
| prod_name | prod_price |
+--------------+------------+
| Fuses | 3.42 |
| Sling | 4.49 |
| .5 ton anvil | 5.99 |
+--------------+------------+
3 rows in set (0.00 sec)
4.下面的SQL语句有问题吗?(尝试在不运行的情况下指出。)
sql
SELECT vend_name
FROM Vendors
ORDER BY vend_name
WHERE vend_country = 'USA' AND vend_state = 'CA';
# 排序(Sorting)是最后进行的操作,必须在使用 ORDER BY 子句之前使用 WHERE 子句。
第六课 通配符进行过滤
like操作符
前面介绍的所有操作符都是针对已知值进行过滤的。不管是匹配一 个还是多个值,测试大于还是小于已知值,或者检查某个范围的值,共 同点是过滤中使用的值都是已知的。但是,这种过滤方法并不是任何时 候都好用。
通配符(wildcard) 用来匹配值的一部分的特殊字符。
搜索模式(search pattern)① 由字面值、通配符或两者组合构 成的搜索条件。
通配符本身实际是SQL的WHERE子句中有特殊含义的字符,SQL支持几 种通配符
谓词 操作符何时不是操作符?答案是在它作为谓词
百分号(%)通配符
sql
mysql> select prod_id , prod_name
-> from products
-> where prod_name like 'jet%';
+---------+--------------+
| prod_id | prod_name |
+---------+--------------+
| JP1000 | JetPack 1000 |
| JP2000 | JetPack 2000 |
+---------+--------------+
2 rows in set (0.01 sec)
通配符可在搜索模式中任意位置使用,并且可以使用多个通配符。 下面的例子使用两个通配符,它们位于模式的两端
sql
mysql> select prod_id ,prod_name
-> from products
-> where prod_name like '%anvil%'
-> ;
+---------+--------------+
| prod_id | prod_name |
+---------+--------------+
| ANV01 | .5 ton anvil |
| ANV02 | 1 ton anvil |
| ANV03 | 2 ton anvil |
+---------+--------------+
3 rows in set (0.00 sec)
通配符也可以出现在搜索模式中间,虽然不常用
sql
mysql> select prod_name
-> from products
-> where prod_name like 's%e';
+-----------+
| prod_name |
+-----------+
| Safe |
+-----------+
1 row in set (0.00 sec)
下划线_通配符
但下划 线只匹配单个字符而不是多个字符
sql
mysql> select prod_id ,prod_name
-> from products
-> where prod_name like '_ ton anvil'
-> ;
+---------+-------------+
| prod_id | prod_name |
+---------+-------------+
| ANV02 | 1 ton anvil |
| ANV03 | 2 ton anvil |
+---------+-------------+
2 rows in set (0.00 sec)
WHERE子句中的搜索模式给出了后面跟有文本的两个通配 符。结果只显示匹配搜索模式的行:第一行中下划线匹配1, 第二行中匹配2。.5 ton anvil产品没有匹配,因为搜索模式要求匹配两 个通配符而不是一个。
sql
mysql> select prod_id,prod_name
-> from products
-> where prod_name like '% ton anvil';
+---------+--------------+
| prod_id | prod_name |
+---------+--------------+
| ANV01 | .5 ton anvil |
| ANV02 | 1 ton anvil |
| ANV03 | 2 ton anvil |
+---------+--------------+
3 rows in set (0.00 sec)
使用通配符的技巧
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该 使用其他操作符。
- 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用 在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起 来是最慢的。
- 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。
1.编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中包含toy一词的产品。
sql
mysql> SELECT prod_name, prod_desc
-> FROM Products
-> WHERE prod_desc LIKE '%toy%';
Empty set (0.00 sec)
2.反过来再来一次。编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中未出现toy一词的产品。这次,按产品名称对结果进行排序。
sql
mysql> select prod_name,prod_desc
-> from products
-> where not prod_desc like '%toy%'
-> order by prod_name;
+----------------+----------------------------------------------------------------+
| prod_name | prod_desc
|
+----------------+----------------------------------------------------------------+
| .5 ton anvil | .5 ton anvil, black, complete with handy hook |
| 1 ton anvil | 1 ton anvil, black, complete with handy hook and carrying case |
| 2 ton anvil | 2 ton anvil, black, complete with handy hook and carrying case |
| Bird seed | Large bag (suitable for road runners)
|
| Carrots | Carrots (rabbit hunting season only)
|
| Detonator | Detonator (plunger powered), fuses not included |
| Fuses | 1 dozen, extra long
|
| JetPack 1000 | JetPack 1000, intended for single use
|
| JetPack 2000 | JetPack 2000, multi-use
|
| Oil can | Oil can, red
|
| Safe | Safe with combination lock
|
| Sling | Sling, one size fits all
|
| TNT (1 stick) | TNT, red, single stick
|
| TNT (5 sticks) | TNT, red, pack of 10 sticks
|
+----------------+----------------------------------------------------------------+
14 rows in set (0.00 sec)
3.编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中同时出现toy和carrots的产品。有好几种方法可以执行此操作,但对于这个挑战题,请使用AND和两个LIKE比较。
sql
mysql> SELECT prod_name, prod_desc
-> FROM Products
-> WHERE prod_desc LIKE '%toy%' AND prod_desc LIKE '%carrots%';
Empty set (0.00 sec)
4.来个比较棘手的。我没有特别向你展示这个语法,而是想看看你根据目前已学的知识是否可以找到答案。编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回在描述中以先后顺序同时出现toy和carrots的产品。提示:只需要用带有三个%符号的LIKE即可。
sql
mysql> select prod_name, prod_desc
-> from products
-> where prod_desc like '%toy%carrots%';
Empty set (0.00 sec)
使用正则表达式进行搜索(补)
正则表达式用正则表达式语言来建立,正则表达式语言是用来完成 刚讨论的所有工作以及更多工作的一种特殊语言。
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '1000'
-> order by prod_name;
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
+--------------+
1 row in set (0.00 sec)
除关键字LIKE被REGEXP替代外,这条语句看上去非常像使用 LIKE的语句。它告诉MySQL:REGEXP后所跟的东西作 为正则表达式(与文字正文1000匹配的一个正则表达式)处理。
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '.000'
-> order by prod_name;
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.01 sec)
正则表达式提供了一种强大且灵活的方式来处理文本数据,尤其在需要进行模式匹配、搜索、替换等操作时非常有用。虽然正则表达式可能在某些情况下性能不如其他方法(例如简单的字符串比较),但它在处理复杂模式和大量数据时仍然是一种非常有效的工具。
正则表达式的优势包括:
- 灵活性和表达力:正则表达式可以描述各种复杂的文本模式,包括字符、字符串、位置、数量等,比简单的字符串比较更具表达力。
- 通用性:正则表达式是一种通用的文本处理工具,可以用于多种编程语言和操作系统。
- 批量处理:正则表达式可以一次性处理大量文本数据,提高处理效率。
- 标准化:正则表达式是一种标准化的文本处理方法,在不同环境下具有一致的语法和行为。
进行or匹配
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '1000|2000'
-> order by prod_name;
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)
匹配几个字符之一
匹配任何单一字符。但是,如果你只想匹配特定的字符,怎么办? 可通过指定一组用[和]括起来的字符来完成
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '[123] Ton'
-> order by prod_name;
+-------------+
| prod_name |
+-------------+
| 1 ton anvil |
| 2 ton anvil |
+-------------+
2 rows in set (0.01 sec)
,[]是另一种形式的OR语句。事实上,正则表达式[123]Ton 为[1|2|3]Ton的缩写,也可以使用后者。但是,需要用[]来定义OR语句 查找什么。
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '1|2|3 Ton'
-> order by prod_name;
+---------------+
| prod_name |
+---------------+
| 1 ton anvil |
| 2 ton anvil |
| JetPack 1000 |
| JetPack 2000 |
| TNT (1 stick) |
+---------------+
5 rows in set (0.00 sec)
这并不是期望的输出。两个要求的行被检索出来,但还检索出 了另外3行。之所以这样是由于MySQL假定你的意思是'1'或 '2'或'3 ton'。除非把字符|括在一个集合中,否则它将应用于整个串。
字符集合也可以被否定,即,它们将匹配除指定字符外的任何东西。 为否定一个字符集,在集合的开始处放置一个^即可。因此,尽管[123] 匹配字符1、2或3,但 [ ^123 ] 却匹配除这些字符外的任何东西
匹配范围
集合可用来定义要匹配的一个或多个字符。
0123456789\]可以简化为\[0-9
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '[1-5] Ton'
-> order by prod_name;
+--------------+
| prod_name |
+--------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
+--------------+
3 rows in set (0.00 sec)
匹配特殊字符
正则表达式语言由具有特定含义的特殊字符构成。我们已经看到.、[]、 |和-等,还有其他一些字符。
sql
#下面的输出是错误的哦
mysql> select vend_name
-> from vendors
-> where vend_name regexp '.'
-> order by vend_name;
+----------------+
| vend_name |
+----------------+
| ACME |
| Anvils R Us |
| Furball Inc. |
| Jet Set |
| Jouets Et Ours |
| LT Supplies |
+----------------+
6 rows in set (0.00 sec)
--下面是正确的
mysql> select vend_name
-> from vendors
-> where vend_name regexp '\\.'
-> order by vend_name;
+--------------+
| vend_name |
+--------------+
| Furball Inc. |
+--------------+
1 row in set (0.00 sec)
\.匹配.,所以只检索出一行。这种处理 就是所谓的转义(escaping),正则表达式内具有特殊意义的所 有字符都必须以这种方式转义。这包括.、|、[]以及迄今为止使用过的 其他特殊字符
在 MySQL 正则表达式中,空白元字符可以表示为以下表格:
元字符 | 描述 |
---|---|
\\n |
匹配换行符(newline) |
\\r |
匹配回车符(carriage return) |
\\t |
匹配制表符(tab) |
\\f |
匹配换页符(form feed) |
\\v |
匹配纵向制表符(vertical tab) |
匹配字符类
字符类 | 描述 |
---|---|
[:alnum:] |
匹配任何一个字母或数字字符(相当于 [A-Za-z0-9] ) |
[:alpha:] |
匹配任何一个字母字符(相当于 [A-Za-z] ) |
[:digit:] |
匹配任何一个数字字符(相当于 [0-9] ) |
[:lower:] |
匹配任何一个小写字母字符(相当于 [a-z] ) |
[:upper:] |
匹配任何一个大写字母字符(相当于 [A-Z] ) |
[:space:] |
匹配任何一个空白字符(包括空格、制表符、换行符等) |
在正则表达式中,重复元字符用于指定匹配的重复次数。以下是一些常见的重复元字符及其描述:
元字符 | 描述 |
---|---|
* |
匹配前面的元素零次或多次。 |
+ |
匹配前面的元素一次或多次。 |
? |
匹配前面的元素零次或一次。 |
{n} |
匹配前面的元素恰好 n 次。 |
{n,} |
匹配前面的元素至少 n 次。 |
{n,m} |
匹配前面的元素至少 n 次,但不超过 m 次。 |
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '\\([0-9] stick?\\)'
-> order by prod_name;
+---------------+
| prod_name |
+---------------+
| TNT (1 stick) |
+---------------+
1 row in set (0.00 sec)
sql
mysql> select prod_name
-> from products
-> where prod_name regexp '[[:digit:]]{4}'
-> order by prod_name;
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)
-- 正则表达式\\([0-9] sticks?\\)需要解说一下。\\(匹配),
-- [0-9]匹配任意数字(这个例子中为1和5),sticks?匹配stick
-- 和sticks(s后的?使s可选,因为?匹配它前面的任何字符的0次或1次出现),\\)匹配)。没有?,匹配stick和sticks会非常困难
正则表达式\\([0-9] sticks?\\)需要解说一下。\\(匹配),
[0-9]匹配任意数字(这个例子中为1和5),sticks?匹配stick
和sticks(s后的?使s可选,因为?匹配它前面的任何字符的0次或1次出
现),\\)匹配)。没有?,匹配stick和sticks会非常困难
定位符
定位符 | 描述 |
---|---|
^ |
匹配输入字符串的开头。 |
$ |
匹配输入字符串的结尾。 |
\b |
匹配单词的边界。 |
\B |
匹配非单词边界。 |
^的双重用途 ^有两种用法。在集合中(用[和]定义),用它 来否定该集合,否则,用来指串的开始处
使REGEXP起类似LIKE的作用 本章前面说过,LIKE和REGEXP 的不同在于,LIKE匹配整个串而REGEXP匹配子串。利用定位 符,通过用^开始每个表达式,用$结束每个表达式,可以使 REGEXP的作用与LIKE一样
第七课 创建计算字段
字段(field) 基本上与列(column)的意思相同,经常互换使 用,不过数据库列一般称为列,而术语字段通常用在计算字段的 连接上。
存储在表中的数据都不是应用程序所需要的。 我们需要直接从数据库中检索出转换、计算或格式化过的数据;而不是 检索出数据,然后再在客户机应用程序或报告程序中重新格式化。
拼接字段
拼接(concatenate) 将值联结到一起构成单个值。
sql
mysql> select concat (vend_name,'(',vend_country,')')
-> from vendors
-> order by vend_name;
+-----------------------------------------+
| concat (vend_name,'(',vend_country,')') |
+-----------------------------------------+
| ACME(USA) |
| Anvils R Us(USA) |
| Furball Inc.(USA) |
| Jet Set(England) |
| Jouets Et Ours(France) |
| LT Supplies(USA) |
+-----------------------------------------+
6 rows in set (0.01 sec)
Concat()拼接串,即把多个串连接起来形成一个较长的串。 Concat()需要一个或多个指定的串,各个串之间用逗号分隔。 上面的SELECT语句连接以下4个元素
- 存储在vend_name列中的名字;
- 包含一个空格和一个左圆括号的串;
- 存储在vend_country列中的国家;
- 包含一个右圆括号的串
sql
mysql> select concat(rtrim(vend_name),'(',rtrim(vend_country),')')
-> from vendors
-> order by vend_name;
+------------------------------------------------------+
| concat(rtrim(vend_name),'(',rtrim(vend_country),')') |
+------------------------------------------------------+
| ACME(USA) |
| Anvils R Us(USA) |
| Furball Inc.(USA) |
| Jet Set(England) |
| Jouets Et Ours(France) |
| LT Supplies(USA) |
+------------------------------------------------------+
6 rows in set (0.01 sec)
# RTrim()函数去掉值右边的所有空格。通过使用RTrim(),各个列都进行了整理。
# Trim函数 MySQL除了支持RTrim()(正如刚才所见,它去掉串右边的空格),还支持LTrim()(去掉串左边的空格)以及Trim()(去掉串左右两边的空格)。
使用别名
从前面的输出中可以看到,SELECT语句拼接地址字段工作得很好。 但此新计算列的名字是什么呢?实际上它没有名字,它只是一个值。如 果仅在SQL查询工具中查看一下结果,这样没有什么不好。但是,一个未 命名的列不能用于客户机应用中,因为客户机没有办法引用它
为了解决这个问题,SQL支持列别名。别名(alias)是一个字段或值 的替换名。别名用AS关键字赋予。请看下面的SELECT语句:
SELECT语句本身与以前使用的相同,只不过这里的语句中计算 字段之后跟了文本AS vend_title。它指示SQL创建一个包含 指定计算的名为vend_title的计算字段。从输出中可以看到,结果与以 前的相同,但现在列名为vend_title,任何客户机应用都可以按名引用 这个列,就像它是一个实际的表列一样。
sql
mysql> select concat(Rtrim(vend_name),'(',rtrim(vend_country),')') as
-> vend_title
-> from vendors
-> order by vend_name;
+------------------------+
| vend_title |
+------------------------+
| ACME(USA) |
| Anvils R Us(USA) |
| Furball Inc.(USA) |
| Jet Set(England) |
| Jouets Et Ours(France) |
| LT Supplies(USA) |
+------------------------+
6 rows in set (0.00 sec)
导出列 别名有时也称为导出列(derived column),不管称为 什么,它们所代表的都是相同的东西
别名的其他用途 别名还有其他用途。常见的用途包括在实际 的表列名包含不符合规定的字符(如空格)时重新命名它,在 原来的名字含混或容易误解时扩充它,等等
执行算数计算
sql
mysql> SELECT prod_id, quantity, item_price
-> FROM OrderItems
-> WHERE order_num = 20005;
+---------+----------+------------+
| prod_id | quantity | item_price |
+---------+----------+------------+
| ANV01 | 10 | 5.99 |
| ANV02 | 3 | 9.99 |
| TNT2 | 5 | 10.00 |
| FB | 1 | 10.00 |
+---------+----------+------------+
4 rows in set (0.00 sec)