一 、排序检索数据:让结果更具逻辑性
默认情况下,SQL检索数据的顺序依赖于数据在表中的物理存储顺序(如插入顺序),这种顺序毫无规律且不稳定。ORDER BY子句的核心作用的是对检索结果进行明确排序,使数据呈现更具逻辑性,方便后续分析与使用。
1.1 基础排序:ORDER BY子句的核心用法
ORDER BY是实现排序的核心关键字,其基本语法为:
sql
SELECT 列名1, 列名2... FROM 表名 ORDER BY 排序列1, 排序列2...;
-
核心规则 :
ORDER BY必须是SELECT语句的最后一条子句,位于WHERE(若有)之后。 -
默认行为 :未指定排序方向时,默认按升序(ASC) 排列(从A到Z、从0到9)。
-
基础示例 :从
Products表中检索产品名称,并按产品名称升序排序:sqlSELECT prod_name FROM Products ORDER BY prod_name;输出结果将按产品名称的字母顺序排列,而非默认的物理存储顺序。
1.2 多列排序:按优先级定义顺序
当需要按多个维度排序时,可在ORDER BY后指定多个列名,列名之间用逗号分隔,排序优先级遵循"先第一列,后第二列"的规则。
-
语法示例 :从
Products表中检索产品ID、价格和名称,先按价格升序,再按名称升序排序:sqlSELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price, prod_name; -
关键说明:仅当第一列存在重复值时,第二列的排序才会生效。例如,若所有产品价格唯一,那么产品名称的排序将无实际意义。
1.3 按列位置排序:简化语法的灵活选择
除了指定列名,ORDER BY还支持按列在SELECT语句中的位置排序(列位置从1开始计数)。
-
语法示例 :与上述多列排序功能一致,用列位置替代列名:
sqlSELECT prod_id, prod_price, prod_name FROM Products ORDER BY 2, 3;其中"2"对应
prod_price,"3"对应prod_name。 -
优点:简化SQL语句,避免重复输入长列名。
-
缺点 :
- 可读性差,他人难以快速理解排序依据;
- 若修改
SELECT语句中列的顺序,ORDER BY的排序逻辑会同步改变,易引发错误; - 无法对未在
SELECT中列出的列进行排序。
1.4 指定排序方向:升序与降序的灵活切换
使用DESC关键字可实现降序排序 (从Z到A、从9到0),ASC(升序)可省略(默认行为)。
-
单列降序示例 :检索产品信息,按价格降序排序(最贵的产品在前):
sqlSELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price DESC; -
多列混合排序示例 :先按价格降序,再按名称升序:
sqlSELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price DESC, prod_name; -
关键注意 :
DESC仅作用于其直接紧跟的列。若需对多个列都进行降序排序,必须为每个列单独指定DESC,例如:sql-- 错误:仅prod_price降序,prod_name仍为升序 SELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price, prod_name DESC; -- 正确:两列均降序 SELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price DESC, prod_name DESC;
1.5 排序的特殊注意事项
- 区分大小写 :文本排序的大小写规则依赖于DBMS及其配置。多数DBMS默认"不区分大小写"(A与a视为相同),但部分系统可配置为区分大小写,此时
'Apple'与'apple'会被视为不同值。 - 非选择列排序 :
ORDER BY支持对未在SELECT中列出的列排序(例如:检索产品名称,但按价格排序),这是合法且常用的操作。
二、 过滤数据:精准获取目标数据
数据库表通常包含大量数据,WHERE子句的核心作用是指定过滤条件,仅检索满足条件的行,避免返回无关数据,提升查询效率并减少网络传输开销。
2.1 WHERE子句的基础用法
WHERE子句用于过滤行数据,其基本语法为:
sql
SELECT 列名1, 列名2... FROM 表名 WHERE 过滤条件;
-
核心规则 :
WHERE子句位于FROM子句之后、ORDER BY子句之前(若有)。 -
基础示例 :从
Products表中检索价格为3.49美元的产品名称和价格:sqlSELECT prod_name, prod_price FROM Products WHERE prod_price = 3.49; -
SQL过滤vs应用过滤 :优先使用
WHERE在数据库端过滤数据,而非在应用程序中过滤。数据库端过滤更高效,且能减少网络传输的数据量;应用端过滤会浪费服务器资源和带宽。
2.2 常用过滤操作符:覆盖多数业务场景
SQL提供多种操作符用于构建过滤条件,以下是书中重点介绍的核心操作符及用法:
2.2.1 等于(=)与不等于(<>/!=)
-
等于(=) :匹配列值与指定值完全相等的行(注意:字符串需用单引号括起,数值无需引号)。
示例:检索供应商ID为DLL01的产品:sqlSELECT prod_name, vend_id FROM Products WHERE vend_id = 'DLL01'; -
不等于(<>/!=) :匹配列值与指定值不相等的行(
<>是ANSI标准,!=为部分DBMS扩展,如MySQL,Microsoft Access仅支持<>)。
示例:检索供应商ID不是DLL01的产品:sqlSELECT prod_name, vend_id FROM Products WHERE vend_id <> 'DLL01';
2.2.2 范围匹配:BETWEEN操作符
BETWEEN用于匹配指定范围内的所有值 ,包含范围的起始值和结束值,语法为BETWEEN 起始值 AND 结束值。
-
示例:检索价格在5美元到10美元之间的产品:
sqlSELECT prod_name, prod_price FROM Products WHERE prod_price BETWEEN 5 AND 10;该语句等价于
prod_price >= 5 AND prod_price <= 10。
2.2.3 空值匹配:IS NULL操作符
NULL表示"无值"(区别于0、空字符串''),判断列值是否为NULL需使用IS NULL(不能用= NULL,SQL中NULL与任何值比较结果均为NULL)。
-
示例:检索没有电子邮件地址(
cust_email为NULL)的顾客名称:sqlSELECT cust_name FROM Customers WHERE cust_email IS NULL; -
注意:
IS NOT NULL用于匹配非空值,示例:检索有电子邮件地址的顾客:sqlSELECT cust_name FROM Customers WHERE cust_email IS NOT NULL;
2.2.4 其他常用操作符
| 操作符 | 说明 | 示例 |
|---|---|---|
> |
大于 | WHERE prod_price > 10(价格大于10美元) |
< |
小于 | WHERE prod_price < 5(价格小于5美元) |
>= |
大于等于 | WHERE prod_price >= 8(价格大于等于8美元) |
<= |
小于等于 | WHERE prod_price <= 3(价格小于等于3美元) |
!> |
不大于(等价于<=) |
WHERE prod_price !> 5(价格不大于5美元) |
!< |
不小于(等价于>=) |
WHERE prod_price !< 10(价格不小于10美元) |
2.3 过滤条件的关键注意事项
- 字符串与数值的引号规则 :字符串类型的列(如
vend_id、prod_name)匹配时,值必须用单引号 括起;数值类型的列(如prod_price、quantity)匹配时,无需加引号。 - NULL的特殊性 :包含
NULL的行不会出现在普通过滤条件中(如WHERE prod_price <> 3.49不会返回prod_price为NULL的行),需单独用IS NULL/IS NOT NULL处理。 - 操作符兼容性 :部分操作符并非所有DBMS都支持(如
!>、!<),优先使用<=、>=等ANSI标准操作符,确保代码可移植性。
三、排序语法速查(ORDER BY)
1. 核心功能
对SELECT检索结果按指定规则排序,解决默认物理存储顺序无规律的问题。
2. 基础语法
| 功能类型 | 语法格式 | 关键说明 |
|---|---|---|
| 单列排序 | SELECT 列1, 列2... FROM 表名 ORDER BY 排序列 [ASC/DESC]; |
- ASC:升序(默认,可省略,如A→Z、0→9) - DESC:降序(如Z→A、9→0) - ORDER BY必须是SELECT最后一条子句 |
| 多列排序 | SELECT 列1, 列2... FROM 表名 ORDER BY 排序列1 [ASC/DESC], 排序列2 [ASC/DESC]; |
按列1优先级排序,仅当列1有重复值时,列2排序才生效 |
| 按列位置排序 | SELECT 列1, 列2, 列3... FROM 表名 ORDER BY 列位置1, 列位置2; |
列位置从1开始计数(如"2"对应SELECT中第2列),不推荐(可读性差、易出错) |
3. 关键示例(基于Products表)
| 需求描述 | SQL语句 |
|---|---|
| 按产品名称升序排序 | SELECT prod_name FROM Products ORDER BY prod_name; |
| 按价格降序、名称升序排序 | SELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price DESC, prod_name; |
| 按列位置(第2列)排序 | SELECT prod_id, prod_price, prod_name FROM Products ORDER BY 2; |
4. 注意事项
DESC作用范围 :仅对紧跟的列生效,多列降序需为每列单独加DESC(如ORDER BY price DESC, name DESC)。- 非选择列排序 :支持对未在
SELECT中列出的列排序(如SELECT prod_name FROM Products ORDER BY prod_price;)。 - 大小写敏感性:文本排序是否区分大小写(如"A"与"a"),依赖DBMS配置(多数默认不区分)。
四、过滤语法速查(WHERE)
1. 核心功能
通过指定条件筛选表中行数据,仅返回满足条件的结果,减少无关数据传输与处理开销。
2. 基础语法
| 功能类型 | 语法格式 | 关键说明 |
|---|---|---|
| WHERE基础用法 | SELECT 列1, 列2... FROM 表名 WHERE 过滤条件; |
- WHERE位于FROM之后、ORDER BY之前 - 过滤条件由"列名+操作符+值"组成 |
| 多条件组合 | (见"高级过滤",需结合AND/OR,详见第5课) |
暂不涉及,核心关注单条件过滤 |
3. 常用操作符与示例(基于Products/Customers表)
| 操作符 | 功能描述 | 语法格式 | 关键示例 | 注意事项 |
|---|---|---|---|---|
= |
等于 | 列名 = 值 |
检索价格=3.49的产品: SELECT prod_name, prod_price FROM Products WHERE prod_price = 3.49; |
数值无需引号,字符串需加单引号 (如vend_id = 'DLL01') |
<>/`!= |
不等于 | 列名 <> 值/列名 != 值 |
检索供应商≠DLL01的产品: SELECT prod_name, vend_id FROM Products WHERE vend_id <> 'DLL01'; |
<>是ANSI标准,!=非通用(如Access仅支持<>) |
BETWEEN |
范围匹配(含边界) | 列名 BETWEEN 起始值 AND 结束值 |
检索价格5~10的产品: SELECT prod_name, prod_price FROM Products WHERE prod_price BETWEEN 5 AND 10; |
等价于>= 起始值 AND <= 结束值,边界值必含 |
IS NULL |
匹配空值(无值) | 列名 IS NULL |
检索无邮箱的顾客: SELECT cust_name FROM Customers WHERE cust_email IS NULL; |
不能用= NULL,NULL与任何值比较均为NULL |
IS NOT NULL |
匹配非空值 | 列名 IS NOT NULL |
检索有邮箱的顾客: SELECT cust_name FROM Customers WHERE cust_email IS NOT NULL; |
- |
>/< |
大于/小于 | 列名 > 值/列名 < 值 |
检索价格>10的产品: SELECT prod_name, prod_price FROM Products WHERE prod_price > 10; |
- |
>=/<= |
大于等于/小于等于 | 列名 >= 值/列名 <= 值 |
检索价格<=5的产品: SELECT prod_name, prod_price FROM Products WHERE prod_price <= 5; |
- |
4. 注意事项
- 引号规则 :字符串值必须用单引号 括起(如
'DLL01'),数值/日期值无需引号(如3.49、2024-01-01)。 - NULL特殊性 :含
NULL的行不会出现在普通过滤中(如WHERE prod_price <> 3.49不会返回prod_price为NULL的行)。 - 数据类型匹配 :过滤条件的值需与列数据类型一致(如数值列不能用字符串过滤,如
prod_price = 'abc'会报错)。
五、常见错误规避
| 错误类型 | 错误示例 | 正确示例 | 原因分析 |
|---|---|---|---|
| ORDER BY位置错误 | SELECT prod_name FROM Products ORDER BY prod_name WHERE prod_price > 5; |
SELECT prod_name FROM Products WHERE prod_price > 5 ORDER BY prod_name; |
ORDER BY必须在WHERE之后 |
| DESC作用范围错误 | SELECT prod_price, prod_name FROM Products ORDER BY prod_price, prod_name DESC; |
SELECT prod_price, prod_name FROM Products ORDER BY prod_price DESC, prod_name DESC; |
DESC仅作用于紧跟的列,多列降序需逐个加 |
| 字符串未加引号 | SELECT prod_name FROM Products WHERE vend_id = DLL01; |
SELECT prod_name FROM Products WHERE vend_id = 'DLL01'; |
字符串值必须加单引号 |
NULL判断用= NULL |
SELECT cust_name FROM Customers WHERE cust_email = NULL; |
SELECT cust_name FROM Customers WHERE cust_email IS NULL; |
NULL不能用=判断,需用IS NULL |
| 按列位置排序易出错 | SELECT prod_price, prod_name FROM Products ORDER BY 1, 2;(后续修改列顺序) |
SELECT prod_price, prod_name FROM Products ORDER BY prod_price, prod_name; |
列位置依赖SELECT列顺序,修改后逻辑易变 |
六、核心原则
- 排序优先用列名:避免按列位置排序,提升代码可读性与可维护性。
- 过滤优先数据库端 :用
WHERE在数据库筛选数据,而非在应用端过滤(减少带宽与资源消耗)。 - 复杂查询分步测试 :先验证
WHERE过滤逻辑,再添加ORDER BY排序,降低调试难度。