首页 / SQLite 入门教程 / SELECT 基础

SQLite 入门教程

SELECT 基础

本教程共 50 篇 · 第 15 篇 · 更新于 2026-07-31

sqliteselect查询别名结果集

15. SELECT:查询基础

本节目标:学完本章你能用 SELECT 从表中取数据,掌握”查指定列""查全表""用 AS 起别名”,并真正理解什么是”结果集”。

开场:查询也是本地运算,没有服务器参与

和插入一样要绷紧一根弦:SQLite 是 serverless(无服务进程)/ 零配置 的。你敲一条 SELECT,SQLite 引擎直接打开那个 .db 文件、在内存里算一遍、把结果返回给你——全程没有独立的数据库服务在后台帮你算。这也意味着查询性能完全取决于你的 SQL 写得好不好、索引建没建,而不是”服务器够不够强”。

SELECT 是整个 SQL 里用得最频繁、也最核心的语句。本章只讲最基础的形状,后面的 WHERE、ORDER BY、JOIN 等都是在它之上叠加条件。把基础打牢,后面全是水到渠成。

结果集(Result Set)是什么

先建立一个最关键的认知:SELECT 不直接”给你看表”,它返回一个”结果集”

结果集可以理解成:SQLite 按照你的指令,从表里挑出若干行、若干列,临时拼成的一张新表格。这张新表只存在于这次查询的返回里,并不会写回数据库文件(除非你用 INSERT INTO ... SELECT 主动存)。它有行有列、有表头,长得和原表一模一样,但它是”计算产物”,不是”原表本身”。

类比:原表是仓库里的一整本账册,SELECT 就像你跟会计说”把账册里所有姓张的客户、只抄姓名和电话给我”——会计重新抄了一份清单递给你,这份清单就是结果集,账册原件一字未动。

查全表:SELECT *

最省事的写法是 SELECT *,星号 * 是”所有列”的简写:

SELECT * FROM users;

命令行里实际效果(记得用 .headers on.mode column 让输出更好看):

sqlite> .headers on
sqlite> .mode column
sqlite> SELECT * FROM users;
id  name   age  email
--  -----  ---  -------------------------
1   张三    28   zhangsan@example.com
2   李四    33   NULL
3   王五    41   wangwu@example.com

SELECT *users 表的每一列、每一行都搬进结果集。

Warning

生产代码里别用 SELECT * 刚才材料里就强调过:* 只在临时测试时图方便。一旦表结构变化(某列被删、新增一列),依赖 * 的程序可能拿到意料之外的列数,轻则逻辑错位、重则崩溃。开发时老老实实写出你真正要的列名,既是契约也是文档。

查指定列:只拿你需要的

绝大多数时候你不需要整行,只关心其中几列。把列名用逗号列出来即可:

SELECT name, email FROM users;
sqlite> SELECT name, email FROM users;
name   email
-----  -------------------------
张三    zhangsan@example.com
李四    NULL
王五    wangwu@example.com

为什么只查指定列更好? 三个理由:第一,返回数据量小,应用处理更快、内存更省;第二,列少了,结果集更聚焦,你一眼就能看到关心的信息;第三,也是最重要的,稳定——表加列不影响你的查询,表改列顺序也不影响。

何时用 *、何时用指定列? 简单粗暴的准则:在 CLI 里手动排查数据、临时看一眼,用 * 省事;写在程序里、要交付给别人或未来自己的,永远写指定列。

AS 别名:给列或表起个临时外号

查询结果里的列名默认就是原表的列名。但有时列名太长、或是你对列做了计算,想让结果集里的表头更友好,就用 AS 起别名:

SELECT name AS 姓名, age AS 年龄 FROM users;
sqlite> SELECT name AS 姓名, age AS 年龄 FROM users;
姓名   年龄
-----  ---
张三    28
李四    33
王五    41

别名只作用于这次查询返回的结果集,不会改变原表结构,也不会写进数据库。它纯粹是为了”显示好看、语义清晰”。

除了给列起别名,AS 也能给起别名,在多表连接(JOIN,后面章节会学)时特别有用,能大幅缩短语句:

SELECT u.name, o.amount
FROM users AS u
JOIN orders AS o ON u.id = o.user_id;

这里把 users 简称为 uorders 简称为 o,后面引用列时写 u.name 就够了。

Tip

别名里的 AS 关键字其实可以省略,SELECT name 姓名SELECT name AS 姓名 等价。但初学者建议保留 AS,可读性更强,一眼能看出”这是在起别名”。另外:如果别名里含空格或中文,需要用引号包起来,例如 SELECT name AS "用户 姓名"

结果集里列的顺序由你定

很多人以为”查出来的列顺序一定和表里一样”,这是误会。结果集里列的出现顺序,完全由你 SELECT 后列出的列名顺序决定,和原表物理顺序无关:

-- 把 age 放前面、name 放后面,结果集也跟着颠倒
SELECT age, name FROM users;

这在实际里很有用:你想让报表”先看到年龄再看姓名”,就不必去改表结构,查询时调一下列顺序即可。再次强调,结果集是临时拼出来的新表,它和原表是两回事——原表怎么存,不影响你怎么查;你怎么查,也不改原表。

DISTINCT 预览:结果去重

有时同一列里会有重复值,比如 orders 表里多个订单可能属于同一个 user_id。如果你只想知道”有哪些用户下过单”(不关心下了几单),可以用 DISTINCT 让结果集只保留不重复的组合:

SELECT DISTINCT user_id FROM orders;

DISTINCT 的完整用法(包括多列去重、和 GROUP BY 的区别)我们留到第 26 章细讲,这里你先知道 SELECT 有”去重”这个能力即可。

SELECT 还能直接计算:不查表也能用

SELECT 不只是”从表里取数”。它还能当计算器——不接任何表,直接算表达式:

SELECT 1 + 1;
SELECT 10 / 5, 2 * 4;
sqlite> SELECT 1 + 1;
2
sqlite> SELECT 10 / 5, 2 * 4;
2|8

这看起来像花拳绣腿,其实很有用:你可以用 SELECT 给每行做运算、拼接字符串、调用函数。比如给每个人的年龄加 1 岁展示(注意这只是结果集里展示,原表 age 不变):

SELECT name, age, age + 1 AS 明年年龄 FROM users;
Note

SELECT 后跟的表达式(Expression)会在结果集的每一行上各算一次。这里 age + 1 是一行一行算的,返回的新列 明年年龄 也属于结果集,原表数据纹丝不动。表达式(Expression)、运算符(Operator)的概念,我们会在第 17 章系统讲。

执行顺序的小秘密

有个反直觉的点值得记住:SELECT 语句里,SELECT(挑列)写在最前面,但 SQLite 实际先执行 FROM(定位表),再执行各种过滤,最后才执行 SELECT(挑列)。所以语义上是”先确定从哪张表取,再决定留下哪些行,最后决定展示哪些列”。理解这个顺序,对你以后写复杂查询、排查”列找不到”的错误很有帮助。

类比小结

SELECT 就是”按指令抄清单”。SELECT * 是”整页照抄”——方便但潦草;SELECT 列名 是”只抄我圈出来的几栏”——精准且稳妥;AS 是”给抄出来的栏目标个更好懂的抬头”;而返回的整张清单,就是结果集:它是 SQLite 现场算出来的临时表格,原件(磁盘上的 .db 文件)一点没动。记住:查询不改数据,只产出数据;且因为 SQLite 没有服务器,这整笔账都是你本机文件 + 引擎现算的。