PostgreSQL SQL 语法基础
环境装好后,我们来系统过一遍 SQL 的基础语法。这一章不涉及高级查询,只讲清"SQL 语句长什么样"——子句顺序、执行顺序、注释、标识符规则。读完你就能看懂任何 SQL 代码的框架。
1. SQL 语句的基本结构
SQL 是"声明式"语言——你描述"想要什么",数据库决定"怎么算"。一条 SELECT 查询由若干子句按固定顺序组成,看这个最经典的模板:
-- SQL 语句以分号结尾,一条 SELECT 通常由这些子句按顺序组成:
SELECT name, age, COUNT(*) AS cnt -- 1. 选哪些列/算什么
FROM users -- 2. 从哪张表
WHERE age >= 18 -- 3. 行级过滤
GROUP BY name, age -- 4. 分组
HAVING COUNT(*) > 1 -- 5. 组级过滤
ORDER BY cnt DESC, name ASC -- 6. 排序
LIMIT 10 OFFSET 0; -- 7. 分页
-- 单行注释用双横线,-- 后到行尾都是注释
/* 多行注释用斜杠星号包裹,
可以跨多行,但不能嵌套 */
/* 块注释也常用于临时禁用一大段 SQL:
SELECT * FROM orders;
*/每个子句的职责要分清:
SELECT:投影——选哪些列、计算什么表达式。*表示所有列。FROM:数据来源——一张表,或多张表 JOIN 后的结果。WHERE:行级过滤——逐行判断条件,留下的进入下一步。GROUP BY:分组——按某些列的值相同的行合并成一组。HAVING:组级过滤——对分组后的结果再过滤(能用聚合函数)。ORDER BY:排序——按列升降序排。LIMIT/OFFSET:分页——跳过多少行,取多少行。
除 SELECT 外其他都可选。最简单的查询就一句 SELECT 1;,连 FROM 都不需要。
2. 执行顺序(关键!)
这是初学者最容易踩的坑:SQL 的书写顺序和执行顺序不一样。理解执行顺序能解释 80% 的"为什么这条 SQL 报错"。
-- 重要!SQL 关键词的"书写顺序"和"执行顺序"不一样
-- 书写顺序:SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT
-- 执行顺序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
-- 因此可以推出几条规则:
-- 1. WHERE 里不能用 SELECT 中起的别名(因为 SELECT 还没执行)
SELECT age * 2 AS double_age FROM users
WHERE age > 18; -- ✅ 正确
-- WHERE double_age > 36; ❌ 错误!别名在 WHERE 里看不到
-- 2. HAVING 可以用聚合函数(WHERE 时还没分组,看不到聚合结果)
SELECT user_id, COUNT(*) AS cnt
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 5; -- ✅ 用聚合函数过滤
-- 3. ORDER BY / LIMIT 在最后,所以能用 SELECT 里的别名
SELECT age * 2 AS double_age FROM users
ORDER BY double_age DESC; -- ✅ ORDER BY 可以用别名把执行顺序记牢:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。从此你写复杂查询就不会再问"为什么别名在 WHERE 里不能用"。
3. 关键字与标识符
SQL 大小写规则有点反直觉,务必记住下面这几条:
-- 1. 关键字不区分大小写:select / SELECT / Select 完全等价
select * from users; -- 完全可以,但社区约定关键字大写
SELECT * FROM users; -- 推荐写法,易读
-- 2. 标识符(表名/列名)默认不区分大小写,但 Postgres 会折叠成小写
CREATE TABLE MyTable (id INT); -- 实际表名变成 mytable
SELECT * FROM MyTable; -- ✅ 能查到
SELECT * FROM mytable; -- ✅ 也能查到
-- 3. 如果想保留大小写或用关键字做列名,用双引号包起来
CREATE TABLE "MyTable" ("select" INT, "order" TEXT);
SELECT "select", "order" FROM "MyTable";
-- 但日常强烈不推荐这么干,自找麻烦
-- 4. 字符串字面量用单引号(不是双引号!)
SELECT 'hello'; -- ✅ 字符串
SELECT "hello"; -- ❌ Postgres 会把 hello 当列名,报错
-- 5. 数字字面量直接写
SELECT 42, 3.14, 1.5e-10;
-- 6. 美元符号引用的字符串(避免转义引号)
SELECT $$It's a 'test'$$; -- 等价于 'It''s a ''test'''
SELECT $tag$包含'单引号'$tag$; -- 自定义标签,适合嵌套最常踩的两个坑:
- 双引号 vs 单引号:单引号包字符串值,双引号包标识符(表名/列名)。把字符串写成双引号是最常见的新手错误。
- 大写表名会被折叠:你写
MyTable,Postgres 实际存的是mytable。如果想保留大写,必须永远用双引号引用,极其麻烦,所以社区惯例是标识符一律小写加下划线。
4. 注释
SQL 注释和很多语言相似:
- 单行注释:
--双横线,到行尾结束。 - 多行注释:用
/* */包裹,可跨多行,不能嵌套。
多行注释常用来临时禁用一段 SQL 调试。注意 -- 必须在行尾或独立行,写在字符串字面量里就不算注释了。
5. 字符串字面量
SQL 字符串的标准写法是单引号包裹。如果字符串内部包含单引号,有两种写法:
- 双写转义:把内部的单引号写成两个
''。如'It''s ok'表示字符串 It's ok。 - 美元符号引用(Postgres 特色):用
$$...$$或带标签的$tag$...$tag$包裹,内部的引号无需转义。写存储过程或包含大量引号的文本时极有用。
6. Postgres 特色方言
除标准 SQL 外,Postgres 有一些独特的语法糖,实战中极其常用:
-- Postgres 有一些"特色"方言,在标准 SQL 上做了扩展:
-- 1. ILIKE:不区分大小写的 LIKE
SELECT * FROM users WHERE name ILIKE 'john%'; -- 匹配 John / JOHN / john
-- 2. ~ 正则匹配(区分大小写),~* 不区分,!~ 不匹配
SELECT * FROM users WHERE name ~ '^A[a-z]+$';
-- 3. :: 类型转换语法(CAST 的简写)
SELECT '2026-08-05'::DATE;
SELECT 42::TEXT;
-- 等价于 CAST('2026-08-05' AS DATE)
-- 4. RETURNING:INSERT/UPDATE/DELETE 后返回修改的行
INSERT INTO users (name) VALUES ('小明') RETURNING id, name;
UPDATE users SET age = 20 WHERE id = 1 RETURNING *;
DELETE FROM users WHERE id = 1 RETURNING name;
-- 5. DISTINCT ON:每组只留第一条(类似窗口函数的简化版)
SELECT DISTINCT ON (user_id) user_id, created_at, total
FROM orders
ORDER BY user_id, created_at DESC;
-- 取每个用户的最新一条订单
-- 6. EXTRACT / date_part 取日期部分
SELECT EXTRACT(YEAR FROM created_at) AS y FROM orders;
SELECT date_part('month', now()) AS m;其中 RETURNING 和 DISTINCT ON 是 Postgres 区别于 MySQL 的两大杀器,后面 DML 和高级查询章节会再展开。
小结
这一章你了解了 SQL 语句的整体骨架、执行顺序、注释规则、标识符约定。下一篇我们看 PostgreSQL 的数据类型——这是定义任何表之前必须搞清楚的事。
← 上一篇 PostgreSQL 安装与 psql
下一篇 PostgreSQL 数据类型 →