SQL
SQL 学习笔记
SQL 是用于定义、查询和操作关系型数据的声明式语言。编写 SQL 时,应先明确目标结果集,再考虑连接、过滤、聚合和执行计划。不同数据库在函数、过程语法和事务行为上存在差异,本文以通用 SQL 为主,并在流程控制部分说明 MySQL 风格语法。
SQL 语句分类
- DDL:定义数据库对象,例如
CREATE、ALTER和DROP。 - DML:写入或修改数据,例如
INSERT、UPDATE和DELETE。 - DQL:查询数据,主要指
SELECT。 - DCL:控制权限,例如
GRANT和REVOKE。 - TCL:控制事务,例如
COMMIT和ROLLBACK。
1 | flowchart LR |
基础查询顺序
1 | SELECT department_id, COUNT(*) AS employee_count |
逻辑处理顺序通常可理解为 FROM、WHERE、GROUP BY、HAVING、SELECT、ORDER BY 和 LIMIT。该顺序解释了为何大多数数据库不能在同一层的 WHERE 中直接引用 SELECT 定义的别名。
CASE WHEN 与 IF THEN
CASE 是表达式,用于在查询或更新语句中根据条件返回一个值。它可以出现在 SELECT、ORDER BY、UPDATE 和聚合表达式中。
1 | SELECT |
条件聚合是 CASE 的常见用途:
1 | SELECT |
IF ... THEN 是存储过程、函数或触发器中的流程控制语句,不能作为标准 SQL 表达式直接放入普通查询。以下为 MySQL 风格示例:
1 | IF total_amount >= 1000 THEN |
部分数据库提供 IF 函数,例如 MySQL 的 IF(condition, value1, value2),但它属于方言功能。需要跨数据库迁移时,应优先使用标准 CASE。
表结构与元数据
MySQL 可使用以下命令查看表结构:
1 | DESCRIBE table_name; |
DESCRIBE 适合快速查看字段、类型、空值与索引信息。SHOW CREATE TABLE 能看到完整建表语句,更适合核对默认值、约束、字符集和存储引擎。跨数据库场景可查询 information_schema.columns。
1 | SELECT column_name, data_type, is_nullable, column_default |
连接查询
INNER JOIN只返回两侧满足连接条件的记录。LEFT JOIN保留左表全部记录,右表无匹配时返回空值。FULL OUTER JOIN保留两侧全部记录,但并非所有数据库都直接支持。CROSS JOIN返回笛卡尔积,使用时应明确结果规模。
1 | SELECT o.id, o.created_at, u.name |
连接条件应写在 ON 中,结果过滤通常写在 WHERE 中。对 LEFT JOIN 的右表字段在 WHERE 中进行非空过滤,会使查询效果接近 INNER JOIN,这是常见逻辑错误。
事务
事务的核心目标是让一组相关修改整体成功或整体失败。
1 | START TRANSACTION; |
实际转账还必须检查第一条更新影响的行数,并对账户行使用适当锁策略。事务应保持简短,避免在事务中等待外部接口或用户输入。
索引与性能
复合索引的列顺序应根据等值过滤、范围过滤、排序和选择性综合确定。索引可以减少扫描量,但会增加写入成本和存储占用。
1 | CREATE INDEX idx_orders_user_created |
优化时应依据执行计划和真实数据分布,重点观察扫描行数、连接方式、临时表和排序操作。避免对索引列进行不必要的函数计算,也要避免使用 SELECT * 读取无关大字段。
安全要求
应用程序必须使用参数化查询,不能通过字符串拼接构造用户输入。
1 | String sql = "SELECT id, name FROM users WHERE email = ?"; |
数据库账户应遵循最小权限原则,读写账户分离,敏感操作保留审计记录,并为备份与恢复设置定期验证流程。






