别名就是给列或表起个临时名字,只在这一次查询里有效。
as 可以省,但省了看不出是别名还是漏逗号。
Demo 里 height * 2 AS double_h 把表头从表达式换成人话;带空格的中文别名要用双引号;
表别名 s 和 c 让多表查询短了一半;
最后撞到一件怪事:where 里用别名,这里能过,MySQL 会报 Unknown column。
上一篇说「算出来的列没名字」, 这一篇给它起名字。 别名看着是小技巧,其实是可读性的第一道关。 它还有一个隐藏作用: 结果集导出成 CSV 时,表头就是别名—— 给别人看的报表,别名起得好不好直接决定人家看不看得懂。
一、列别名:把表达式换成人话
语法:列名或表达式 AS 别名。 别名的意思就是「这一次查询里,这一列叫这个名字」。
起别名的三个理由:表头好看(height * 2 变成 double_h)、
方便引用(order by 里能用)、方便程序取值(结果集的列名固定)。
别名只在本次查询有效,不会改表结构,也不会存下来。
二、as 能省,但别省
SELECT name n FROM students 也合法,n 就是别名。
但省掉 as 会有歧义:SELECT name n, height h 里,
裸眼看不出 n 是别名还是漏了一个逗号,改代码时容易看错。
本书一律写 as。 多敲四个字符,换来的是「一眼就知道这是别名」。
三、特殊别名:带空格、带中文,要用双引号
别名里有空格、有中文标点、撞上关键字,就得用双引号包起来:AS "学生 姓名"、
AS "身高(厘米)"。
这里的双引号是「标识符引用」的正经用途——
这也解释了为什么字符串要用单引号:两个引号各有分工,别混。
实务上别名尽量别带空格:程序取值时麻烦(row["学生 姓名"]),
导出 CSV 时表头也会带着空格。 用下划线或驼峰更省事。
四、表别名:多表查询的简称
FROM students AS s JOIN classes AS c 之后,s.name、c.teacher 就代替了全名。
三个好处:少打字、字段重名时能分清(两张表都有 name,
写 s.name 和 c.name 一目了然)、自连接时必须用(同一张表出现两次,不起别名没法区分)。
表别名还有个实际影响:
一旦起了别名,原表名就不能再用了。 FROM students AS s 之后再写 students.name 会报错。
五、别名在 where 里:这里能,MySQL 不能
Demo 实测:WHERE double_h > 340 在这边跑通了,给了 5 行。
但这是 SQLite 的扩展,不是标准 SQL。
同一句搬到 MySQL 上会报 Unknown column 'double_h' in 'where clause'。
因为标准规定:where 里只能引用表里真实存在的列。
为什么会有这条规定:执行顺序。
where 在「算 select 那一列」之前就跑完了,那时别名还不存在;order by 在之后,所以看得见。
规范写法:把表达式重写一遍,或者套一层子查询(外层就能引用内层的别名了)。
六、小结
教材小结:用 as 给列或表起别名,别名让结果更好读;别名带特殊字符时要用引号包起来。 本课补三条:一是别名只在本次查询有效,不改表; 二是 where 里别用别名(这边能过是扩展,MySQL 报错); 三是表别名一旦起了,原表名就不能再用。
七、动手 Demo:别名四种用法,一次撞墙
Demo 六段:列别名、省掉 as、特殊别名、表别名,然后是 where 与 order by 对别名的两种态度。 第五段是这一篇的重点—— 同一句别名,两个子句一个认一个不认,而这里连 where 都认了,那是引擎放宽的结果。
import _q46 as Q
c = Q.con()
c.execute("SELECT name, height * 2 AS double_h FROM students LIMIT 3")
c.execute("SELECT name n, height h FROM students LIMIT 2") # 省掉 as
c.execute('SELECT name AS "学生 姓名" FROM students LIMIT 2') # 特殊别名
# 表别名
c.execute("SELECT s.name, c.teacher FROM students AS s "
"JOIN classes AS c ON s.class_id = c.id LIMIT 3")
# where 里用别名:这里能过(SQLite 扩展),MySQL 报 Unknown column
c.execute("SELECT name, height * 2 AS double_h FROM students "
"WHERE double_h > 340")
# order by 用别名:标准写法,两边都认
c.execute("SELECT name, height * 2 AS double_h FROM students "
"ORDER BY double_h DESC LIMIT 3")
实跑输出:
--------------------------------------------------------------------
第十课:别名,以及它在 where 里为什么用不了
--------------------------------------------------------------------
列别名:给算出来的列起个名
SQL> SELECT name, height * 2 AS double_h FROM students LIMIT 3
name double_h
------------------
张伟 345.00
王芳 320.40
李娜 330.00
(3 行)
**不起别名,表头就是 `height * 2` 这种表达式;起了别名,表头干净。**
as 可以省略,但不建议省
SQL> SELECT name n, height h FROM students LIMIT 2
n h
----------------
张伟 172.50
王芳 160.20
(2 行)
**省掉 as 也能过,但一眼看不出是别名还是漏了逗号。** **本书一律写 as。**
特殊别名:带空格、带中文,要加引号
SQL> SELECT name AS "学生 姓名", height AS "身高(厘米)" FROM students LIMIT 2
学生 姓名 身高(厘米)
---------------------------
张伟 172.50
王芳 160.20
(2 行)
**别名里有空格或中文标点,必须用双引号包起来。**
**这里双引号是「标识符引用」的意思,正好是它的正经用途。**
表别名:多表查询时的简称
SQL> SELECT s.name,
c.teacher FROM students AS s JOIN classes AS c ON s.class_id = c.id LIMIT 3
name teacher
-----------------
张伟 马老师
王芳 马老师
李娜 孔老师
(3 行)
**`s` 和 `c` 就是表别名。多表查询里不加别名,字段名一撞就得写全路径。**
别名能不能用在 where 里:这里能,MySQL 不能
SQL> SELECT name, height * 2 AS double_h FROM students WHERE double_h > 340
name double_h
------------------
张伟 345.00
刘洋 356.60
杨帆 350.20
黄磊 360.40
周涛 348.00
(5 行)
**这一句在这里跑通了,但它是 SQLite 的扩展,不是标准 SQL。**
**同一句搬到 MySQL 上会报 `Unknown column 'double_h' in 'where clause'`**——
因为标准规定 where 里只能引用表里真实存在的列。
**所以别这么写。** 依赖它,代码就绑死在这个引擎上了。
SQL> SELECT name, height * 2 AS double_h FROM students ORDER BY double_h DESC LIMIT 3
name double_h
------------------
黄磊 360.40
刘洋 356.60
杨帆 350.20
(3 行)
**order by 用别名是标准的、两边都认。**
**原因是执行顺序:where 在「算 select 那一步」之前跑完,那时别名还不存在。**
**order by 在之后,所以看得见。**
**要按算出来的值筛选,规范写法是把表达式重写一遍,或者套一层子查询。**
第一段列别名。 表头从 height * 2 变成 double_h。
第二段省 as。 能跑,表头是 n 和 h,但可读性差。
第三段特殊别名。 学生 姓名 带空格、身高(厘米) 带中文括号,都得用双引号包。
第四段表别名。 s 与 c 一代,SQL 短了一半。
第五段 where 用别名。 这里给了 5 行、
没报错——但正文里说清了:这是扩展,MySQL 会报 Unknown column。
第六段 order by 用别名。 标准写法,两边都认。
30 秒实验
- 把第三段别名里的空格去掉,还能不加引号吗?
- (先想再跑)
FROM students AS s之后再写students.name,会怎样? - 在 MySQL 里想让
where double_h > 340能跑,该怎么改?
常见误区
- 在 where 里用 select 别名。 这边能过是运气,MySQL 直接报 Unknown column。
- 表别名起了还用原表名。 起了
s之后students.name就失效了,报的是「找不到表」, 很难联想到是别名惹的。 - 别名带空格或中文标点。 程序取值、导 CSV、写文档都别扭,用下划线最省事。
自测三问(点开对答案)
1. 别名会改变表结构吗? —— 不会。别名只在那一次查询的结果集里有效,不写回表,也不存下来。 2. 为什么 order by 能用别名,where 不能? —— 执行顺序不同:where 在算出 select 列之前就执行,别名还不存在;order by 在其后。 3. 表别名起了之后要注意什么? —— 原表名不能再用;字段重名时用别名前缀区分;自连接必须起别名。列挑完了、名字也起好了,下一篇开始筛行——where,以及那个能让结果差三倍的优先级坑。
- ☐ (本篇完,下一篇 3.3 条件子句:where)