跳转到主要内容

6 从表中查询数据

用明确的列名、别名和过滤条件读取示例表 fruits。

现在 fruits 已经有了数据,可以开始读取这些行了。SELECT * 返回所有列;列出具体列名,则只返回这些列,并按列名的书写顺序排列。除非加上 ORDER BY,否则结果没有确定的行序;即使今天看起来有序,明天也未必如此。

本章要点

  • 用 SELECT * FROM table 读取所有列
  • 选择特定列,并控制它们在结果中的顺序
  • 将 SELECT 与 WHERE、ORDER BY 组合使用
  • 为什么 SELECT * 适合临时查询,却在应用代码中存在风险
  • 结果列的名称,以及如何修改它们
准备示例表

开始本章前,先在练习数据库中运行 psql -f source/create-table.sql -f source/insert.sql postgres。这两个文件分别在第 16 章和第 24 章介绍;学习这些 SELECT 章节之前,表必须已经存在。

示例

示例 6.1 从表中查询数据
-- All columns. The order matches CREATE TABLE.
SELECT * FROM fruits ORDER BY id;

-- Specific columns, in the order you list them
SELECT name, id FROM fruits ORDER BY id;

-- Renaming output columns
SELECT id AS fruit_id, name AS fruit_name FROM fruits ORDER BY id LIMIT 3;

-- Combining a filter and an order
SELECT id, name
FROM fruits
WHERE id BETWEEN 2 AND 4
ORDER BY name;

-- Counting rows
SELECT count(*) AS total FROM fruits;

先运行 create-table.sql 和 insert.sql,再运行本章示例。SELECT * 按物理列顺序返回所有列。明确列出列名,就能完全控制结果的结构;当数据要交给按位置映射列的应用代码时,这一点尤其重要。AS 只修改输出中的列名,不会改变表中的任何内容。

* 和操作符两侧的空格可以省略;SQL 解析器对空白字符相当宽容。查询分成多行书写很常见,列数超过两列时也推荐这样做。

运行示例

运行方式:

$ psql -f source/select-from-table.sql postgres
 id  |   name
-----+-----------
   1 | apple
   2 | banana
   3 | cherry
   4 | date
   5 | elderberry
 101 | fruit_1
 102 | fruit_2
 103 | fruit_3
(8 rows)

    name    | id
------------+-----
 apple      |   1
 banana     |   2
 ...

常见陷阱

  • SELECT * FROM big_table; 会通过网络取回每一行的每一列,既慢又浪费资源。请列出实际需要的列。
  • 输出列名并不保证唯一。SELECT id, id FROM fruits 的两列都叫 id,应用使用的驱动可能无法妥善处理这种情况。
  • 在应用代码中,应优先明确指定列名,而不是使用 SELECT *。当表结构中新增一列时,SELECT * 的结果结构就会改变,可能使依赖特定列顺序或列数的代码出错。
提示

探索数据时,可以在 psql 中用 \x 切换扩展显示:一条记录的每一列各占一行。用这种方式阅读宽行会轻松得多。

动手练习

运行 SELECT * FROM fruits WHERE id > 100;,只查看生成的那些行。然后运行 SELECT name FROM fruits ORDER BY name;,让名称按字母顺序排列。再尝试 SELECT id || ': ' || name AS label FROM fruits;,用字符串拼接操作符 || 构造一个标签列。

下载

SQL 文件: select-from-table.sql · 全部示例文件 · 准备工作