数据库入门到初级 · 第 07/22 篇。实验口径:MySQL 8.4、InnoDB、utf8mb4。案例:小型商城。
商品表里有编号、名称、价格、库存等字段,但商品列表也许只需要名称和价格。SELECT 让我们从完整数据中挑出当前任务需要的内容。读懂它,后面条件、排序和统计就有了基础。
本篇及后续查询使用第 3 篇导入的数据,或第 5、6 篇手动准备的数据。每次建立新连接后,先执行 USE shop_lab;。
1. 从两列开始
SELECT name, price
FROM products
ORDER BY id;
按样例数据,应得到机械键盘 199.00、无线鼠标 89.00、笔记本支架 129.00、数据线 29.00、旧款耳机 299.00。FROM 指定来源,SELECT 指定输出列;ORDER BY id 让示例结果便于核对。

你可以把结果集理解成数据库交回的一张临时答卷。查询没有删除未选中的字段,原表的库存和创建时间仍然存在。
2. 星号可以用,但要知道取了什么
SELECT * FROM products;
* 表示取所有列。临时查看表很方便,但在应用代码里,显式写字段能更清楚地表达依赖,也避免把暂时不需要的大字段或敏感字段一并读取。它还让接口更容易控制返回内容。
这不是说所有 SELECT * 都很慢。查询快慢取决于数据量、条件、索引和返回内容,后面会逐步学习。这里先养成“知道自己在取什么”的习惯。
3. 别名只是结果列的新名字
SELECT name AS product_name,
price AS unit_price,
stock AS available_stock
FROM products
ORDER BY id;
结果表头变成 product_name、unit_price 和 available_stock,数据库字段本身没有改名。AS 可以省略,但初学时保留它更易读。
中文展示名也可以使用反引号,例如 AS `商品名称` ;实际应用通常保留稳定的英文列名,由界面负责翻译。反引号用于标识符,单引号用于字符串值,不要混淆。
4. 计算列:边查边算
SELECT id, name, price, stock,
price * stock AS listed_stock_value
FROM products
ORDER BY id;
机械键盘这一行计算出 199 × 20 = 3980.00。这是“按当前标价估算的库存金额”,不是库存成本,也不是已经实现的销售收入。SQL 计算结果是否有业务意义,取决于字段含义和计算口径。
计算列同样只影响结果展示,不会在表里自动增加一列。若字段包含 NULL,算术结果通常也会是 NULL,第 4 篇的空值知识在这里就派上用场了。
5. DISTINCT:对整个选择组合去重
SELECT DISTINCT user_id FROM orders ORDER BY user_id;
SELECT DISTINCT user_id, status FROM orders ORDER BY user_id, status;
第一条得到用户 1 和 2。第二条得到 (1, paid)、(2, cancelled)、(2, pending) 三种组合。DISTINCT 不是“只对第一列去重,其他列随便带出来”,它作用于整组选出的列。
如果你本来需要统计每个用户有多少订单,就应该使用下一阶段的分组聚合,不能简单加 DISTINCT 代替业务计算。
6. 最常见的书写错误
字段之间要用英文逗号分隔;字符串要使用配对的英文单引号;不要把终端命令粘进 SQL 提示符。Unknown column 常表示字段名拼错,或在这个查询上下文里不可见。先 DESCRIBE products;,通常比反复猜字段名更快。
练习与答案
练习一:列出商品编号、名称和“全部库存卖出后的标价金额”。
SELECT id, name, price * stock AS listed_stock_value
FROM products
ORDER BY id;
练习二:查询订单出现过哪些状态。
SELECT DISTINCT status FROM orders ORDER BY status;
答案包括 cancelled、paid、pending。结果展示和数据修改是两件事;想改变原表,要使用前一篇的增删改命令。
上一篇:第 06 篇 · 系列目录 · 下一篇:第 08 篇