select 只做两件事:挑列、挑行。 这一篇只管挑列——
列可以是表里的、可以是算出来的、也可以是常量。
Demo 里 SELECT * 出三行四列;height * 2 出 345.00;
my table 里那个叫 select 的列不加反引号直接语法错;
一条 SQL 写成五行照样跑——引擎只看分号。
上一章讲「怎么说」,这一篇开始真查数据。 select 是全书出现最多的关键字,
后面 16 章都在给它加各种子句。
顺序要记住:select(挑列)→ from(从哪张表)→ where(筛行)→ group by。
再往后是 having → order by → limit。 这一篇只碰最前面两个。
一、select 的基本形状:挑哪几列
最小的一句是 SELECT 列名 FROM 表名;。 select 后面写要哪几列,from 后面写从哪张表取。
SELECT * 是「所有列」,写起来省事,但产品代码里尽量别用:
表一加字段,取回来的列就变了,程序里按下标取值的地方会错位;
大字段(TEXT、BLOB)也会被白白拉回来。
列的顺序自己定,不必跟建表顺序一致;同一列也可以写两次(少见但合法)。
二、列可以算:表达式、常量、函数
select 后面不只放列名,还能放表达式:height * 2、price * 0.9、concat(name, '同学')。
算出来的东西没有名字,得给别名。
也能放常量:SELECT '固定值' AS tag, id FROM students——这一招在导数据、加标记时很常用。
还能完全不带表:SELECT 1 + 1; 在 8.0 里合法,用来测连接通不通最快。 本沙箱也支持。
三、特殊列名:反引号是保命符
列名叫 select、表名带空格、字段名是 order——这些不报错的办法只有一个:用反引号包起来。
反引号在 MySQL 里是「标识符引用」,和字符串的单引号是两回事。
标准 SQL 用双引号,但 MySQL 默认把双引号当字符串,所以还是用反引号。
这就是命名规则那条「别用关键字」的真实原因:不是洁癖,
是每次写它都得记得加反引号,早晚漏一次。
四、换行说明:一条语句可以写很多行
引擎只认分号,不认换行。 你把 select、from、where 各写一行,或者全挤一行,结果一样。
但人要在乎:一个子句一行,where 里的每个 and 各占一行,
这样别人(和三个月后的你)才看得懂。
图形工具里还有个实际影响:编辑器里选中哪一段就只跑哪一段,所以语句之间空一行,方便单独跑。
五、小结
教材小结:select 语句用于查询,select * 取所有列、也可以只取指定列;一条语句可以分多行书写。
本课补三条:一是产品代码别写星号,列会随表结构漂移;
二是列可以是表达式、常量、函数,算出来的都要起别名;三是特殊列名一律反引号,别赌。
六、动手 Demo:从星号到指定列,再到反引号
Demo 五段:先 SELECT * 看全表,再只挑两列,再让列参与运算,然后撞一次特殊列名,
最后看一条 SQL 写成五行。
这一篇的每一段都在回答同一个问题:select 后面到底能放什么。
import sqlite3
c = sqlite3.connect(":memory:")
# 这里直接借样例库(六张表)
import _q46 as Q
c = Q.con()
c.execute("SELECT * FROM classes") # 所有列
c.execute("SELECT name, teacher FROM classes") # 指定列
c.execute("SELECT name, height * 2 AS double_h "
"FROM students LIMIT 3") # 列参与运算
# 特殊列名要反引号
c.execute("CREATE TABLE `my table` (`select` TEXT, `full name` TEXT)")
c.execute("SELECT `select`, `full name` FROM `my table`")
# 一条 SQL 可以写很多行,引擎只看分号
c.execute("""SELECT id, name, height
FROM students
WHERE class_id = 1""")
实跑输出:
--------------------------------------------------------------------
第九课:select 的第一层——挑列
--------------------------------------------------------------------
查全部列:星号,方便但别写进产品代码
SQL> SELECT * FROM classes
id name teacher room
------------------------------------
1 一班 马老师 A101
2 二班 孔老师 A102
3 三班 曹老师 B201
(3 行)
**三行四列全出来了,但列的顺序依赖建表顺序。**
**产品代码里写星号,表一加字段,取到的列就变了。**
查指定列:要哪几列写哪几列
SQL> SELECT name, teacher FROM classes
name teacher
-----------------
一班 马老师
二班 孔老师
三班 曹老师
(3 行)
**列的顺序可以自己定**,不必跟建表顺序一致。
列可以参与运算:查出来的不一定是原样
SQL> SELECT name, height, height * 2 AS double_h FROM students LIMIT 3
name height double_h
-----------------------------
张伟 172.50 345.00
王芳 160.20 320.40
李娜 165.00 330.00
(3 行)
**`height * 2` 不是表里的列,是查的时候算出来的——所以必须给它一个别名(下一节专讲)。**
特殊列名:带空格、带关键字,都要反引号
SQL> SELECT `select`, `full name` FROM `my table`
select full name
---------------------
a 张伟
(1 行)
**表名带空格、列名叫 select,全得用反引号包起来。**
**所以命名规则里那条「别用关键字」不是洁癖,是省事。**
换行说明:一条 SQL 可以写很多行
SQL> SELECT id, name, height FROM students WHERE class_id = 1
id name height
-----------------------
1 张伟 172.50
2 王芳 160.20
6 杨帆 175.10
9 周涛 174.00
(4 行)
**引擎只看分号,不在乎你在哪换行。** **但人要在乎:一个子句一行,比挤成一行好读得多。**
第一段星号。 三行四列全出来,列顺序就是建表顺序。
第二段挑列。 只要 name, teacher 两列,顺序可以自己定,不必跟建表一致。
第三段列运算。 height * 2 算出 345.00、320.40、330.00,
表头就是那个表达式——所以下一节讲别名。
第四段特殊列名。 表名 my table 带空格、列名叫 select,全靠反引号才过。
第五段换行。 写成五行照样跑出四行结果,引擎只看分号。
30 秒实验
SELECT * FROM classes与SELECT id, name, teacher, room FROM classes结果一样吗?- (先想再跑)
SELECT 1 + 1;不带 from 能跑吗? - 把
SELECT *换成SELECT name, id,列的顺序变了吗?
常见误区
- 产品代码写
select *。 表加一个字段,取回的列就多一个,按下标取值的代码立刻错位。 - 特殊列名不加反引号。 报的是语法错,指向的位置还很靠前,看起来像是前面写错了。
- 把一条 SQL 挤成一行。 能跑,但改的时候找不到该改哪一段,而且图形工具里没法只选中一半运行。
自测三问(点开对答案)
1. `SELECT *` 有什么风险? —— 列随表结构变化,程序按下标取会错位;还会把 TEXT/BLOB 这类大字段白拉回来。 2. select 后面能放什么? —— 列名、表达式、常量、函数;算出来的列建议起别名。 3. 表名或列名撞上关键字怎么办? —— 用反引号包起来(MySQL 写法);标准 SQL 用双引号,但 MySQL 默认把双引号当字符串。算出来的列没有名字,下一篇专门讲怎么给它起名——别名,以及它在 where 里为什么有时用不了。
- ☐ (本篇完,下一篇 3.2 使用别名:as)