除了基础的等于、大于和小于,SQL 还提供了一些实用条件,用来处理“包含某段文字”“属于几个值中的一个”“处于某个范围内”或“这个字段没有值”。LIKE、IN、BETWEEN 和 NULL 条件会让日常查询灵活很多。
使用 LIKE 做模式匹配
name = 'A' 只能找到名字刚好等于 A 的数据,不能找到 Alice。要查找以 A 开头的名字,可以使用 name LIKE 'A%'。百分号是 通配符(Wildcard),代表任意数量的字符。
A% — 以 A 开头
%a — 以 a 结尾
%Coffee% — 任意位置包含 Coffee
O%ka — O 开头、ka 结尾
SELECT *
FROM products
WHERE name LIKE '%Coffee%';LIKE 是否区分大小写取决于数据库和配置。入门阶段先掌握百分号代表“任意数量字符”,真实项目中再确认所用产品的规则。
把字符串送进正确的匹配区
把每个字符串拖到“匹配”或“不匹配”。触屏设备可以先点字符串,再点目标区域。
LIKE 'A%' → Alice知识测验
使用 IN 查询多个可能值
Tokyo、Osaka 或 Kyoto 可以写成三个 OR,但候选值多时很冗长。city IN ('Tokyo', 'Osaka', 'Kyoto') 表示 city 属于列表中的任意一个值。数字也适用,例如 id IN (1, 3, 4)。要排除列表,可以使用 NOT IN。
SELECT *
FROM users
WHERE city IN ('Tokyo', 'Osaka', 'Kyoto');使用 BETWEEN 查询范围
price BETWEEN 40 AND 80 通常包含两个边界值,大致等于 price >= 40 AND price <= 80。BETWEEN 也常用于日期;带具体时间的 DATETIME 或 TIMESTAMP 需要额外留意结束边界。
观察 BETWEEN 的边界
改变价格或日期的上下界,特别比较刚好等于边界与差 1 的结果。BETWEEN 同时包含两端。
| id | name | city | |
|---|---|---|---|
| 1 | Alice | [email protected] | Tokyo |
| 2 | Bob | [email protected] | Osaka |
| 3 | Chris | [email protected] | Tokyo |
| 4 | Diana | [email protected] | Kyoto |
沙盒已准备好,不会连接真实数据库。知识测验
NULL 表示没有已知值
NULL 通常表示没有值、未知或暂未提供。它不是数字 0,也不是空字符串。Bob 的 phone 为 NULL,表示数据库没有他的号码,而不是存了字符串“NULL”。
| id | name | phone |
|---|---|---|
| 1 | Alice | 09012345678 |
| 2 | Bob | NULL |
| 3 | Chris | 08012345678 |
| 4 | Diana | '' |
不能使用 phone = NULL。查找缺失号码必须写 phone IS NULL;查找有号码的数据写 phone IS NOT NULL。NULL 是未知值,不能当作普通值用等号比较。
空字符串也不同于 NULL。空字符串是长度为 0 的真实字符串;NULL 表示没有已知值。因此 phone IS NULL 和 phone = '' 可能返回完全不同的 Row。
这些条件可以组合。例如 Tokyo 或 Osaka 中 email 不缺失的用户,可以使用 IN 加 IS NOT NULL;价格在 20 到 80 之间且名称包含 o 的商品,可以使用 BETWEEN 加 LIKE。
知识测验
设计三个 LIKE 模式
针对 products.name 写三条查询:
① 以 Coffee 开头;
② 以 Mug 结尾;
③ 任意位置包含 board。每条只改变 LIKE 后的模式。写完后分别说明百分号为什么放在那里。
范围与缺失值
写两条查询:
① 返回价格在 40 到 80(含边界)的商品 name 和 price;
② 返回 phone 没有值的用户。再回答:phone 为空字符串的用户会不会被第二条查询选中?为什么?
可选:通用练习数据脚本
DROP TABLE IF EXISTS products;
DROP TABLE IF EXISTS users;
CREATE TABLE users (id INTEGER, name VARCHAR(100), phone VARCHAR(30));
CREATE TABLE products (id INTEGER, name VARCHAR(100), price DECIMAL(10, 2));
INSERT INTO users VALUES
(1, 'Alice', '09012345678'), (2, 'Bob', NULL),
(3, 'Chris', '08012345678'), (4, 'Diana', '');
INSERT INTO products VALUES
(1, 'Keyboard', 80.00), (2, 'Mouse', 40.00),
(3, 'Coffee Mug', 15.00), (4, 'Backpack', 60.00);