- 1. 什么是 SQL
- 2. 常见列类型(column type)
- 3. 主键与外键
- 4. 索引
- 5. SQL 语句的常见分类
- 6. 常用查询语法
- 7. 建表、改表(加列、删列、重命名表)、删表
- 8. 分表、分库
- 9. SQL 执行顺序
- 10. 学习资源
1. 什么是 SQL
SQL 全称 Structured Query Language,用于操作关系型数据库中的数据和数据库对象。
常见的关系型数据库包括:
- MySQL
- PostgreSQL
- SQLite
- Oracle
- SQL Server
这些数据库都受到 SQL 标准影响,但并不是所有语法都完全通用。
关系型数据库通常由一组相互关联的表组成。每张表有:
- 列:描述字段,例如 id、name、created_at
- 行:一条具体记录
可以把它理解为“比 Excel 更适合存储、约束和查询数据的表格系统”。
2. 常见列类型(column type)
在 SQL/关系型数据库里,每一列(column)都有一个数据类型(type),用于限制该列可以存储什么样的数据。
选择合适的数据类型,会影响:
- 数据正确性
- 存储空间
- 查询性能
- 可维护性
2.1 数值类型(Numeric Types)
| 类型 | 描述 | 示例 |
|---|---|---|
| INT / INTEGER | 整数 | 42 |
| BIGINT | 大整数 | 1234567890123 |
| SMALLINT | 小整数 | 1000 |
| DECIMAL(p,s) / NUMERIC(p,s) | 精确小数(固定精度) | DECIMAL(10,2) → 最多 10 位,总有 2 位小数 |
| FLOAT / REAL / DOUBLE | 浮点数(近似) | 3.14159 |
说明:
- 金额、价格、比例这类对精度敏感的数据,优先用 DECIMAL / NUMERIC
- 浮点数适合科学计算,不适合直接存钱
2.2 字符类型(String / Text Types)
| 类型 | 描述 | 示例 |
|---|---|---|
| CHAR(n) | 固定长度字符 | ‘abc ‘(长度 3) |
| VARCHAR(n) | 可变长度字符 | ‘hello’ |
| TEXT / CLOB | 大文本 | ‘Lorem ipsum…’ |
说明:
- CHAR(n) 常用于长度固定的数据,例如国家码、状态码
- VARCHAR(n) 更常用,适合大多数字符串字段
- 字符串字面量通常用单引号,例如 ‘Alice’
- 字符串中若包含单引号,通常写成两个单引号,例如 ‘I’‘m Bob’
2.3 日期时间类型(Date/Time Types)
| 类型 | 描述 | 示例 |
|---|---|---|
| DATE | 年-月-日 | 2026-04-07 |
| TIME | 时:分:秒 | 14:30:00 |
| DATETIME / TIMESTAMP | 日期+时间 | 2026-04-07 14:30:00 |
| YEAR | 年份 | 2026 |
说明:
- TIMESTAMP 和 DATETIME 在不同数据库中的行为并不完全一样
- PostgreSQL 常用 TIMESTAMP
- MySQL 同时有 DATETIME 和 TIMESTAMP
- 如果业务涉及时区,设计时要提前考虑“是否存时区”或“是否统一用 UTC”
2.4 布尔类型(Boolean Type)
| 类型 | 描述 | 示例 |
|---|---|---|
| BOOLEAN / BOOL | 真/假 | TRUE / FALSE |
说明:
- BOOLEAN 是常见写法,但不同数据库实现不同
- MySQL 中 BOOLEAN 本质上是 TINYINT(1) 的别名
- SQL Server 没有标准 BOOLEAN,通常使用 BIT
2.5 二进制类型(Binary / Blob)
| 类型 | 描述 | 示例 |
|---|---|---|
| BINARY(n) | 固定长度二进制 | 0x01FF |
| VARBINARY(n) | 可变长度二进制 | 0xA1B2C3 |
| BLOB | 大二进制对象 | 图片、文件 |
2.6 JSON / 枚举类型(部分数据库特有)
| 类型 | 描述 | 示例 |
|---|---|---|
| JSON | JSON 数据 | ’{“name”:”Alice”}’ |
| ENUM | 枚举 | ‘small’,’medium’,’large’ |
2.7 选类型的建议
- 金额、积分、汇率:优先 DECIMAL / NUMERIC
- 用户名、标题、手机号:通常用 VARCHAR
- 超长正文:考虑 TEXT
- 时间字段:先明确是否要处理时区
- 想要更强可移植性时,少依赖 ENUM、YEAR 这类方言类型
3. 主键与外键
在关系型数据库中,主键(Primary Key)和外键(Foreign Key)是最核心的概念之一,用于保证数据的唯一性和表之间的关联。
3.1 主键(Primary Key)
主键用来唯一标识表中的每一行记录。一个表只能有 一个主键,但主键可以由多列组成(复合主键)。
- 唯一性 每行数据的主键值都不相同
- 非空 主键列不能为 NULL
- 自动索引 数据库会自动为主键建立索引,提高查询效率
示例:
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
);
复合主键示例:
CREATE TABLE orders (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id)
);
3.2 外键(Foreign Key)
外键用于建立 表与表之间的关联。外键列引用另一个表的主键或唯一键,从而保证数据一致性。
- 参照性完整性 外键值必须在被引用表的主键中存在,或者为 NULL
- 可为空 外键列可以允许 NULL(表示没有关联)
- 可级联操作 可以设置 ON DELETE CASCADE 或 ON UPDATE CASCADE 自动更新/删除关联数据
示例:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
order_date DATE,
FOREIGN KEY (user_id) REFERENCES users(id)
);
这里 user_id 是外键,引用 users 表的 id 列,保证订单一定属于某个用户。
带级联的外键示例:
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
含义:
- 删除用户时,相关订单也会被删掉
- 更新用户主键值时,关联记录同步更新
级联操作很方便,但要谨慎,避免误删大量数据。
4. 索引
在数据库中,索引(Index)是提高查询效率的重要手段,相当于书的目录,让数据库可以快速找到需要的数据。大多数数据库索引基于 B+ 树实现。
4.1 索引有什么用
- 加快 WHERE 条件过滤
- 加快 JOIN 关联
- 在某些场景下优化 ORDER BY、GROUP BY
- 对唯一约束提供支持
4.2 索引的代价
索引不是越多越好。索引会带来:
- 更多存储开销
- 更慢的 INSERT
- 更慢的 UPDATE
- 更慢的 DELETE
因为数据变了,索引也要一起维护。
4.3 常见索引类型
- 主键索引(Primary Key Index)
CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50));自动为主键列建立索引,唯一且非空。
- 唯一索引(Unique Index)
CREATE UNIQUE INDEX idx_email ON users(email);保证列值唯一,可在非主键列上创建。
- 普通索引(Index / Non-Unique Index)
CREATE INDEX idx_name ON users(name);仅用于加快查询,允许重复值。
- 组合索引(Composite Index)
CREATE INDEX idx_name_email ON users(name, email);索引覆盖多列,顺序重要,查询时最好按索引顺序。
4.4 全文索引和空间索引
- 全文索引(Fulltext Index)
CREATE FULLTEXT INDEX idx_content ON articles(content);用于文本搜索,支持 MATCH … AGAINST 搜索文本。
- 空间索引(Spatial Index)
CREATE SPATIAL INDEX idx_location ON places(location);用于 GIS / 坐标数据,支持 POINT, GEOMETRY 类型。
全文索引、空间索引都很常见,但它们不是通用入门 SQL 的核心部分,而且不同数据库支持方式差异很大。例如:
- MySQL 有 FULLTEXT INDEX
- PostgreSQL 更常见的是全文检索能力配合 tsvector
- GIS 相关索引在不同数据库中也有不同实现
5. SQL 语句的常见分类
5.1 DDL
Data Definition Language,数据定义语言,定义和修改数据库结构(表、索引、视图等)。常见语句:
- CREATE 创建数据库、表、视图、索引等
- ALTER 修改已有数据库对象结构
- DROP 删除数据库对象
- TRUNCATE 清空表数据(保留表结构)
5.2 DML
Data Manipulation Language,数据操作语言,用来增删改查数据。常见语句:
- SELECT 查询数据
- INSERT 插入数据
- UPDATE 更新数据
- DELETE 删除数据
Note
- UPDATE 和 DELETE 执行之前最好先使用 SELECT 确认约束的数据集合是否是自己的预期。
- 有的资料把 SELECT 单独分类成 DQL。
5.3 DCL
Data Control Language,数据控制语言,控制数据库访问权限和安全。常见语句:
- GRANT 授权用户权限
- REVOKE 收回用户权限
5.5 TCL
Transaction Control Language,事务控制语言,管理事务,确保数据一致性。常见语句:
- COMMIT 提交事务,永久保存更改
- ROLLBACK 回滚事务,撤销未提交更改
- SAVEPOINT 设置事务保存点,可回滚到此点
- SET TRANSACTION 设置事务属性
6. 常用查询语法
6.1 查(SELECT)
SELECT name, age FROM users;
取哪些字段。
FROM 查询的数据来源,可以是表,也可以是临时结果集。
6.2 筛(WHERE)
SELECT * FROM users WHERE age > 18;
过滤条件
6.3 排(ORDER BY)
ORDER BY age DESC;
排序
6.4 聚(GROUP BY)
SELECT city, COUNT(*) FROM users GROUP BY city;
分组聚合,GROUP BY 后,只能 SELECT 分组字段 or 聚合函数
6.5 连(JOIN)
SELECT u.name, o.amount
FROM users u
JOIN orders o ON u.id = o.user_id;
连接多表
6.6 套(子查询)
SELECT name FROM users
WHERE id IN (SELECT user_id FROM orders);
7. 建表、改表(加列、删列、重命名表)、删表
7.1 建表 CREATE TABLE
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP
);
7.2 增加列 ALTER TABLE
ALTER TABLE users
ADD COLUMN phone VARCHAR(20);
7.3 删除列
ALTER TABLE users
DROP COLUMN phone;
7.4 重命名表
ALTER TABLE users
RENAME TO app_users;
说明:
- 不同数据库在 ALTER TABLE 的细节上可能略有不同
- 写迁移脚本前要确认当前数据库的语法
7.5 删表 DROP TABLE
DROP TABLE app_users;
危险操作建议:
- 先确认环境是不是生产库
- 先确认是否有备份
8. 分表、分库
分库分表不是 SQL 基础语法,而是数据库架构层面的设计问题。
8.1 垂直拆分
按业务拆,例如:
- 用户表放到用户库
- 订单表放到订单库
优点:
- 业务边界清晰
- 单库压力降低
代价:
- 跨库查询和事务更复杂
8.2 水平拆分
按数据行拆,例如按 user_id 取模,把同一张大表拆到多个表或多个库中。
优点:
- 单表数据量下降
- 可以分摊存储和查询压力
代价:
- 路由复杂
- 聚合查询复杂
- 扩容和迁移复杂
9. SQL 执行顺序
SELECT DISTINCT column, AGG_FUNC(column_or_expression), …
FROM mytable
JOIN another_table
ON mytable.column = another_table.column
WHERE constraint_expression
GROUP BY column
HAVING constraint_expression
ORDER BY column ASC/DESC
LIMIT count OFFSET COUNT;
常见的逻辑执行顺序可以理解为:
- FROM
- JOIN
- WHERE
- GROUP BY
- HAVING
- SELECT
- DISTINCT
- ORDER BY
- LIMIT / OFFSET
这也是为什么:
- WHERE 里不能直接使用 SELECT 阶段才产生的别名
- HAVING 是对分组后的结果再做筛选
10. 学习资源
基础
进阶
刷题