SQL 是跟数据库说话的语言,一句话分五类:DDL 动结构、DML 动数据、DQL 只读、DCL 动权限、
TCL 动事务。 本书用到前四类,第五类只在第 15 章露一次面。
Demo 三类各跑一句;
然后撞两次书写规矩:CREATE TABLE order 报 near "order": syntax error,加反引号才过;
SELECT "abc" 在这边给 abc,但它靠的是「找不到列就退化成字符串」这条旧规矩,
不是「双引号表示字符串」。
上一篇把数据库装好了,这一篇开始说它听得懂的话。 语法这块只有三条硬规矩(分号、引号、反引号),其余都是习惯。 它也是全书的语法公约,后面每一篇都按这里定的规矩写。
一、SQL 是语言,不是「MySQL 的操作命令」
SQL 全称 Structured Query Language,1974 年在 IBM 提出,后来成了 ANSI/ISO 标准。
MySQL、PostgreSQL、SQL Server、Oracle 都实现它。
同一个意思每家都有方言:分页 MySQL 写 LIMIT、SQL Server 写 TOP、Oracle 8i 得套 ROWNUM。
所以「会 SQL」的意思是「会标准那部分,再记住目标产品的方言」。
本书只用 MySQL 方言,但凡是标准写法能过的,都尽量用标准写法——这样换库时少改几行。
二、五类语句:先记住它们管什么
DDL(数据定义):CREATE/ALTER/DROP/TRUNCATE——动表结构。
这一类要格外小心,很多是没法回滚的。
DML(数据操纵):INSERT/UPDATE/DELETE——动表里的行。
DQL(数据查询):SELECT——只读不写。
标准里把它归在 DML,习惯上单列,因为九成的活都在这。
DCL(数据控制):GRANT/REVOKE——动权限,第 16 章讲。
TCL(事务控制):COMMIT/ROLLBACK/SAVEPOINT——第 15 章讲。
三、三条硬规矩:分号、单引号、反引号
一条语句以分号结尾(客户端靠它断句)。 字符串用单引号,里面的单引号写两个:'it''s'。
标识符(表名、字段名)撞上关键字时,用反引号包起来:`order`。
反引号是 MySQL 的写法,标准 SQL 用双引号,但 MySQL 默认把双引号当字符串,
所以两边会打架——统一用反引号最省事。
双引号在这边也能给出字符串,但那是因为「找不到叫 abc 的列,就退化成字符串字面量」,
属于历史遗留。
一旦开启 ANSI_QUOTES,这条退路就没了,同一句立刻报错。 别依赖它:字符串一律单引号。
四、命名规则:四条硬要求,两条软习惯
硬要求:字母或下划线开头;只用字母、数字、下划线;不许是保留字;长度别超 64 个字符。
软习惯:全小写加下划线(order_detail、student_id);
表名用单数还是复数,全库统一——最怕一半 user 一半 users。
三个别做:用中文当表名(能跑,但到处要加引号)、用 user/order/desc/key 当名字、
靠大小写区分两张表。
五、小结
教材小结:SQL 是操作关系型数据库的标准语言,按功能分 DDL、DML、DQL、DCL、TCL 几类; 语句以分号结尾,关键字不区分大小写,标识符有命名规则。 本课补三条:一是方言差异集中在分页、日期函数、字符串拼接这三处; 二是标识符撞关键字就加反引号,字符串一律单引号;三是命名全小写加下划线,别拿大小写当区分。
六、动手 Demo:三类语句各一句,再撞两条书写规矩
Demo 六段:先列五类语句,再真跑 DDL/DML/DQL 各一句,
然后试「关键字当表名」「双引号」「单引号套单引号」,最后讲命名规则。
两处报错都是真撞的——near "order": syntax error 和我预想的一样,
SELECT "abc" 却出乎意料地没报错,这一点在正文里照实说明。
import sqlite3
c = sqlite3.connect(":memory:")
# DDL:动结构
c.execute("CREATE TABLE t_ddl (id INTEGER PRIMARY KEY, "
"name TEXT, price REAL)")
# DML:动数据
c.execute("INSERT INTO t_ddl (name, price) VALUES ('篮球', 128.00), "
"('足球', 156.00)")
# DQL:只读
c.execute("SELECT id, name, price FROM t_ddl WHERE price >= 150")
# 关键字当表名:不加反引号报错,加了才过
c.execute("CREATE TABLE order (id INTEGER)")
c.execute("CREATE TABLE `order` (id INTEGER)")
# 双引号在这边的真实行为
c.execute("SELECT \"abc\"")
# 单引号里的单引号写两个
c.execute("SELECT 'it''s ok'")
实跑输出:
--------------------------------------------------------------------
第六课:SQL 的五类语句与三条书写规矩
--------------------------------------------------------------------
一句 SQL 分五类,本书用到四类
DDL(定义):create/alter/drop/truncate —— 动结构
DML(操纵):insert/update/delete —— 动数据
DQL(查询):select —— 只读不写(标准里归在 DML,习惯上单列)
DCL(控制):grant/revoke —— 动权限
TCL(事务):commit/rollback/savepoint —— 动事务
真跑三类各一句
SQL> CREATE TABLE t_ddl (id INTEGER PRIMARY KEY, name TEXT, price REAL)
完成
SQL> INSERT INTO t_ddl (name, price) VALUES ('篮球', 128.00), ('足球', 156.00)
影响 2 行
SQL> SELECT id, name, price FROM t_ddl WHERE price >= 150
id name price
-----------------------
2 足球 156.00
(1 行)
**结构、数据、查询三件事各归各的语句,这是 SQL 最外层的一张地图。**
关键字不能直接当表名,要加反引号
SQL> CREATE TABLE order (id INTEGER)
报错:near "order": syntax error
SQL> CREATE TABLE `order` (id INTEGER)
完成 ← 反引号把它标成「标识符」,不是关键字
**反引号是 MySQL 的写法,SQLite 也兼容。**
**标准 SQL 用双引号(`"order"`),但 MySQL 默认把双引号当字符串,两边会打架。**
双引号:两边现在都给字符串,但这是「将就」
SELECT "abc" -> 'abc'
**这句没报错,给的就是字符串 abc。** 但它不是「双引号表示字符串」的意思,
**而是「找不到叫 abc 的列,就退化成字符串」。**
**MySQL 默认模式下的结果一样,原因却不同:它真把双引号当字符串。**
**两边现在都给 abc,但一旦开启 `ANSI_QUOTES`(MySQL)或严格模式,**
**双引号就变成「标识符」,同一句立刻报找不到列。**
**所以结论只有一条:字符串一律用单引号,双引号留给标准 SQL 的标识符,别混用。**
单引号里的单引号,写两个
SQL> SELECT 'it''s ok' AS s1, 'He said ''hi''' AS s2
s1 s2
-------------------------
it's ok He said 'hi'
(1 行)
**两个单引号表示一个单引号**,这是 SQL 的标准写法,不用反斜杠(反斜杠是 MySQL 的扩展,
换个库就不认)。
命名规则:四条硬要求,两条软习惯
**硬要求**:字母或下划线开头;只能用字母、数字、下划线;不许用保留字;长度别超 64。
**软习惯**:全小写加下划线(`order_detail`);表名用单数还是复数,全库统一就行。
**别做的事**:用中文当表名(能跑但到处要加引号)、用 `user`/`order`/`desc` 当名字、
靠大小写区分两张表。
第一段列五类。 定义、操纵、查询、控制、事务,
各管一件事,混起来就会写出「用 DDL 去改数据」这种怪东西。
第二段真跑三类。 price >= 150 只捞出足球一行,结构、数据、查询三件事在三句里各归各位。
第三段关键字当表名。 CREATE TABLE order 直接报 near "order": syntax error,
加反引号就过——反引号的意思是「这是名字,不是关键字」。
第四段双引号。 SELECT "abc" 给了 abc,没报错;
原因是「找不到列就退化成字符串」,不是「双引号表示字符串」。
这条退路在 ANSI_QUOTES 下没有,所以别依赖。
第五段单引号套单引号。 'it''s ok' 输出 it's ok,两个单引号表示一个,这是标准写法,
比反斜杠可移植。
第六段命名规则。 四条硬要求、两条软习惯、三个别做。
30 秒实验
- 把
price >= 150改成price >= 128,命中几行? - (先想再跑)
CREATE TABLE "order" (id INTEGER)在这边能过吗?在 MySQL 默认模式下呢? SELECT '它''s'和SELECT '它\'s'在这边结果一样吗?
常见误区
- 用双引号写字符串。 MySQL 默认能过,但开了 ANSI_QUOTES 就报错; SQLite 那边更是靠「退化」这条旧规矩撑着。
- 表名直接叫
order/user/desc。 全是保留字,不加反引号就语法错, 而且这种错只在某些语句上出现,很难查。 - 靠大小写区分表名。 Windows 上能跑、Linux 上找不到表,这类 bug 只在部署那天爆。
自测三问(点开对答案)
1. SQL 的五类语句各管什么? —— DDL 管结构(create/alter/drop/truncate)、DML 管数据(insert/update/delete)、 DQL 管查询(select)、DCL 管权限(grant/revoke)、TCL 管事务(commit/rollback)。 2. 标识符撞上关键字怎么办? —— 用反引号包起来(MySQL 写法);标准 SQL 用双引号,但 MySQL 默认把双引号当字符串。 3. 为什么字符串要用单引号? —— 单引号是标准写法,两边都认; 双引号在 MySQL 默认是字符串、开了 ANSI_QUOTES 就变标识符,行为随配置变,不能依赖。语法骨架有了,接下来是「每个字段该用什么类型」—— 这一篇是本课与 MySQL 差异最大的地方。
- ☐ (本篇完,下一篇 2.2 数据类型)