1. MySQL核心SQL语句概述
作为一名数据库管理员,掌握MySQL的核心SQL语句是基本功。SQL(Structured Query Language)是与关系型数据库交互的标准语言,就像我们与Linux系统打交道需要掌握bash命令一样。MySQL作为最流行的开源关系型数据库,其SQL语法虽然与其他数据库有细微差别,但核心概念是相通的。
SQL语言主要分为四大类:
- DDL(Data Definition Language):数据定义语言,用于创建、修改和删除数据库对象
- DML(Data Manipulation Language):数据操作语言,用于数据的增删改查
- DQL(Data Query Language):数据查询语言,专门用于数据检索
- DCL(Data Control Language):数据控制语言,用于权限管理
提示:在实际工作中,运维人员更关注DDL和DCL,而开发人员则更频繁使用DML和DQL。但作为专业人员,我们应该全面掌握这些语句。
2. 数据库管理操作
2.1 创建数据库
创建数据库是数据库管理的第一步。以下是创建数据库的标准语法:
sql复制CREATE DATABASE [IF NOT EXISTS] database_name
[DEFAULT CHARACTER SET charset_name]
[COLLATE collation_name];
实际案例:
sql复制-- 创建支持中文的数据库
CREATE DATABASE school_db DEFAULT CHARACTER SET utf8mb4;
-- 安全创建(避免重复创建报错)
CREATE DATABASE IF NOT EXISTS school_db CHARACTER SET utf8mb4;
注意事项:
- 数据库名不要以数字开头
- 名称应简洁明了,反映业务用途
- 强烈建议指定字符集,避免中文乱码问题
- 生产环境应限制普通用户的DROP DATABASE权限
2.2 查看数据库信息
查看数据库信息是日常维护的重要操作:
sql复制-- 查看所有数据库
SHOW DATABASES;
-- 查看特定数据库的创建语句(含字符集信息)
SHOW CREATE DATABASE school_db;
输出示例:
code复制+----------+---------------------------------------------------------------------+
| Database | Create Database |
+----------+---------------------------------------------------------------------+
| school_db| CREATE DATABASE `school_db` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+---------------------------------------------------------------------+
2.3 修改数据库
修改数据库主要是调整字符集:
sql复制ALTER DATABASE school_db CHARACTER SET utf8mb4;
重要提示:修改数据库字符集不会影响已存在的表,只会影响后续创建的表。要完全解决中文问题,需要同时修改数据库和表的字符集。
2.4 删除数据库
删除数据库是不可逆操作,务必谨慎:
sql复制DROP DATABASE [IF EXISTS] database_name;
3. 数据表管理操作
3.1 创建数据表
创建表是数据库设计的核心。以下是标准语法:
sql复制CREATE TABLE [IF NOT EXISTS] table_name (
column1 datatype [constraints],
column2 datatype [constraints],
...
) [ENGINE=storage_engine] [DEFAULT CHARSET=charset_name];
学生表示例:
sql复制CREATE TABLE students (
id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '学号',
name VARCHAR(50) NOT NULL COMMENT '姓名',
age TINYINT UNSIGNED NOT NULL DEFAULT 18 COMMENT '年龄',
gender ENUM('男','女') NOT NULL DEFAULT '男' COMMENT '性别',
admission_date DATE NOT NULL COMMENT '入学日期',
PRIMARY KEY (id),
UNIQUE KEY uk_name (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生信息表';
建表规范:
- 表名应简洁有意义,避免使用MySQL保留字
- 每个表都应设置主键(通常为自增ID)
- 字段应选择合适的数据类型,避免空间浪费
- 建议所有字段都设置NOT NULL约束,并给出默认值
- 为字段和表添加注释,方便维护
- 字符集统一使用utf8mb4以支持完整Unicode字符(包括emoji)
3.2 查看表结构
了解表结构是操作表的前提:
sql复制-- 查看表的基本结构
DESC students;
-- 查看表的详细创建语句
SHOW CREATE TABLE students;
-- 查看数据库中所有表
SHOW TABLES;
3.3 修改表结构
随着业务变化,经常需要调整表结构:
sql复制-- 添加新列
ALTER TABLE students ADD COLUMN phone CHAR(11) NOT NULL COMMENT '手机号' AFTER gender;
-- 修改列定义
ALTER TABLE students MODIFY COLUMN name VARCHAR(100) NOT NULL COMMENT '学生姓名';
-- 重命名列
ALTER TABLE students CHANGE COLUMN admission_date enroll_date DATE NOT NULL COMMENT '入学日期';
-- 删除列
ALTER TABLE students DROP COLUMN phone;
-- 添加索引
ALTER TABLE students ADD INDEX idx_age (age);
-- 修改表注释
ALTER TABLE students COMMENT='2023级学生信息表';
注意事项:
- 大表结构变更可能会锁表,应在业务低峰期进行
- 生产环境变更前应先在测试环境验证
- 重要变更应做好备份
3.4 复制表
复制表是数据迁移和备份的常用手段:
sql复制-- 只复制表结构
CREATE TABLE students_copy LIKE students;
-- 复制表结构及数据
CREATE TABLE students_backup AS SELECT * FROM students;
3.5 删除表
删除表是不可逆操作,需特别谨慎:
sql复制DROP TABLE [IF EXISTS] table_name;
4. 数据操作语言(DML)
4.1 插入数据
插入数据是数据库的基本操作:
sql复制-- 完整插入(指定所有列)
INSERT INTO students VALUES(NULL, '张三', 20, '男', '2023-09-01');
-- 指定列插入(推荐)
INSERT INTO students(name, age, gender, enroll_date)
VALUES('李四', 19, '女', '2023-09-01');
-- 批量插入(高效方式)
INSERT INTO students(name, age, gender, enroll_date) VALUES
('王五', 21, '男', '2023-09-01'),
('赵六', 20, '女', '2023-09-01'),
('钱七', 22, '男', '2023-09-01');
4.2 更新数据
更新数据需要谨慎,避免误操作:
sql复制-- 更新单个记录
UPDATE students SET age = 21 WHERE id = 1;
-- 更新多个字段
UPDATE students SET age = age + 1, gender = '男' WHERE name = '张三';
-- 使用LIMIT限制更新范围(安全做法)
UPDATE students SET enroll_date = '2023-09-15' WHERE gender = '女' LIMIT 10;
重要提示:UPDATE语句务必带上WHERE条件,否则会更新整张表!生产环境建议先使用SELECT验证WHERE条件。
4.3 删除数据
删除数据需格外小心:
sql复制-- 删除特定记录
DELETE FROM students WHERE id = 5;
-- 使用LIMIT限制删除数量
DELETE FROM students WHERE age > 25 LIMIT 100;
-- 清空表(不可恢复)
TRUNCATE TABLE students_backup;
注意事项:
- DELETE语句也应始终使用WHERE条件
- 大表删除数据可能导致性能问题,建议分批删除
- TRUNCATE比DELETE更快,但无法恢复且会重置自增值
5. 数据查询语言(DQL)
5.1 基础查询
sql复制-- 查询所有列
SELECT * FROM students;
-- 查询特定列
SELECT id, name, age FROM students;
-- 使用别名
SELECT id AS 学号, name AS 姓名, age AS 年龄 FROM students;
-- 去重查询
SELECT DISTINCT age FROM students;
-- 条件查询
SELECT * FROM students WHERE age > 20 AND gender = '男';
-- 排序
SELECT * FROM students ORDER BY age DESC, name ASC;
-- 分页查询
SELECT * FROM students LIMIT 10 OFFSET 20; -- 等价于 LIMIT 20, 10
5.2 聚合查询
sql复制-- 计数
SELECT COUNT(*) FROM students;
SELECT COUNT(DISTINCT age) FROM students;
-- 求和、平均、最大最小值
SELECT
SUM(age) AS total_age,
AVG(age) AS avg_age,
MAX(age) AS max_age,
MIN(age) AS min_age
FROM students;
-- 分组统计
SELECT gender, COUNT(*) AS count, AVG(age) AS avg_age
FROM students
GROUP BY gender;
-- HAVING筛选分组结果
SELECT age, COUNT(*) AS count
FROM students
GROUP BY age
HAVING count > 5;
5.3 多表连接查询
sql复制-- 内连接
SELECT s.name, s.age, c.course_name, c.score
FROM students s
INNER JOIN courses c ON s.id = c.student_id;
-- 左连接
SELECT s.name, c.course_name
FROM students s
LEFT JOIN courses c ON s.id = c.student_id;
-- 子查询
SELECT name, age
FROM students
WHERE age > (SELECT AVG(age) FROM students);
6. 数据控制语言(DCL)
6.1 用户管理
sql复制-- 创建用户
CREATE USER 'dev_user'@'%' IDENTIFIED BY 'password123';
-- 修改密码
ALTER USER 'dev_user'@'%' IDENTIFIED BY 'new_password';
-- 删除用户
DROP USER 'dev_user'@'%';
6.2 权限管理
sql复制-- 授予权限
GRANT SELECT, INSERT, UPDATE ON school_db.* TO 'dev_user'@'%';
-- 授予所有权限
GRANT ALL PRIVILEGES ON school_db.* TO 'admin'@'localhost';
-- 查看权限
SHOW GRANTS FOR 'dev_user'@'%';
-- 撤销权限
REVOKE INSERT ON school_db.* FROM 'dev_user'@'%';
7. 事务控制语言(TCL)
sql复制-- 开始事务
START TRANSACTION;
-- 执行SQL操作
INSERT INTO students(name) VALUES('事务测试');
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
-- 提交或回滚
COMMIT; -- 确认执行
-- 或
ROLLBACK; -- 取消操作
8. 字符集与中文支持
MySQL中正确处理中文需要确保字符集设置正确:
sql复制-- 查看支持的字符集
SHOW CHARACTER SET;
-- 查看当前字符集设置
SHOW VARIABLES LIKE '%character%';
SHOW VARIABLES LIKE '%collation%';
-- 修改配置文件my.cnf永久生效
[mysqld]
character_set_server=utf8mb4
字符集选择建议:
- utf8mb4是MySQL5.5.3+推荐的字符集,完全支持Unicode(包括emoji)
- 避免使用latin1等不支持中文的字符集
- 确保客户端连接也使用相同的字符集
9. 数据类型详解
9.1 数值类型
| 类型 | 存储空间 | 范围 | 描述 |
|---|---|---|---|
| TINYINT | 1字节 | -128~127 | 小整数 |
| SMALLINT | 2字节 | -32768~32767 | 中等整数 |
| INT | 4字节 | -2147483648~2147483647 | 标准整数 |
| BIGINT | 8字节 | -2^63~2^63-1 | 大整数 |
| FLOAT | 4字节 | 约7位精度 | 单精度浮点 |
| DOUBLE | 8字节 | 约15位精度 | 双精度浮点 |
| DECIMAL(M,D) | 变长 | 取决于M,D | 精确小数 |
9.2 字符串类型
| 类型 | 最大长度 | 描述 |
|---|---|---|
| CHAR(n) | 255字符 | 定长字符串,适合短且长度固定的数据 |
| VARCHAR(n) | 65535字节 | 变长字符串,适合长度变化的数据 |
| TEXT | 65535字节 | 长文本数据 |
| LONGTEXT | 4GB | 超长文本数据 |
| ENUM | 65535个值 | 枚举类型,只能选择预定义值 |
9.3 日期时间类型
| 类型 | 格式 | 范围 | 描述 |
|---|---|---|---|
| DATE | YYYY-MM-DD | 1000-01-01~9999-12-31 | 日期值 |
| TIME | HH:MM:SS | -838:59:59~838:59:59 | 时间值 |
| DATETIME | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00~9999-12-31 23:59:59 | 日期时间 |
| TIMESTAMP | YYYY-MM-DD HH:MM:SS | 1970-01-01 00:00:01~2038-01-19 03:14:07 | 时间戳,自动更新 |
10. 约束条件详解
10.1 主键约束
sql复制-- 单列主键
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50)
);
-- 多列主键
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id)
);
10.2 外键约束
sql复制CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
order_date DATE,
FOREIGN KEY (user_id) REFERENCES users(id)
);
10.3 唯一约束
sql复制CREATE TABLE products (
id INT PRIMARY KEY,
product_code VARCHAR(20) UNIQUE,
name VARCHAR(100)
);
10.4 检查约束
sql复制CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100),
salary DECIMAL(10,2),
CHECK (salary > 0)
);
11. 索引优化
11.1 创建索引
sql复制-- 单列索引
CREATE INDEX idx_name ON students(name);
-- 多列复合索引
CREATE INDEX idx_age_gender ON students(age, gender);
-- 唯一索引
CREATE UNIQUE INDEX uk_email ON users(email);
11.2 索引使用原则
- 为经常出现在WHERE、ORDER BY、GROUP BY子句中的列创建索引
- 为经常用于表连接的列创建索引
- 避免为频繁更新的列创建过多索引
- 考虑使用复合索引减少索引数量
- 定期分析索引使用情况,删除无用索引
12. 备份与恢复
12.1 使用mysqldump备份
bash复制# 备份单个数据库
mysqldump -u root -p school_db > school_db_backup.sql
# 备份所有数据库
mysqldump -u root -p --all-databases > full_backup.sql
# 备份特定表
mysqldump -u root -p school_db students courses > tables_backup.sql
12.2 恢复数据
bash复制# 命令行恢复
mysql -u root -p school_db < school_db_backup.sql
# MySQL客户端恢复
mysql> USE school_db;
mysql> SOURCE /path/to/backup.sql;
13. 性能优化建议
- 避免使用SELECT *,只查询需要的列
- 为常用查询条件添加合适的索引
- 使用EXPLAIN分析查询执行计划
- 合理设计表结构,避免过度规范化或反规范化
- 对大表考虑分区或分表策略
- 定期优化表:
OPTIMIZE TABLE table_name - 监控慢查询日志,优化耗时操作
14. 常见问题解决方案
14.1 中文乱码问题
现象:插入或查询的中文显示为乱码
解决方案:
- 确保数据库、表和连接都使用utf8mb4字符集
- 检查客户端工具(如Navicat、命令行)的字符集设置
- 在连接字符串中明确指定字符集:
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8
14.2 忘记root密码
重置步骤:
- 停止MySQL服务
- 启动MySQL跳过权限检查:
mysqld_safe --skip-grant-tables & - 连接MySQL并更新密码:
sql复制UPDATE mysql.user SET authentication_string=PASSWORD('newpass') WHERE User='root'; FLUSH PRIVILEGES; - 重启MySQL服务
14.3 大表删除数据缓慢
优化方案:
- 分批删除:
DELETE FROM large_table WHERE id < 100000 LIMIT 10000; - 创建新表保留需要的数据,然后重命名替换
- 使用pt-archiver等工具辅助删除
15. 实用技巧
15.1 查看表大小
sql复制SELECT
table_name AS '表名',
round(data_length/1024/1024, 2) AS '数据大小(MB)',
round(index_length/1024/1024, 2) AS '索引大小(MB)',
round((data_length+index_length)/1024/1024, 2) AS '总大小(MB)'
FROM information_schema.TABLES
WHERE table_schema = 'school_db'
ORDER BY (data_length+index_length) DESC;
15.2 生成测试数据
sql复制-- 快速生成连续数字
SELECT a.N + b.N*10 + c.N*100 + 1 AS num
FROM
(SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a,
(SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) b,
(SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) c
LIMIT 1000;
15.3 查询执行计划分析
sql复制EXPLAIN SELECT * FROM students WHERE age > 20 ORDER BY name;
通过分析EXPLAIN结果可以了解:
- 是否使用了索引
- 查询类型(全表扫描、索引扫描等)
- 需要扫描的行数
- 是否使用了临时表或文件排序
16. 安全最佳实践
- 遵循最小权限原则,只授予用户必要的权限
- 避免在应用代码中使用root或高权限账户
- 定期审计用户权限:
SELECT * FROM mysql.user; - 密码应复杂并定期更换
- 限制远程访问,只允许必要的IP连接
- 定期备份并验证备份的可用性
- 保持MySQL版本更新,及时修补安全漏洞
17. 版本特性差异
17.1 MySQL 5.7 vs 8.0
- 默认字符集:5.7默认为latin1,8.0默认为utf8mb4
- JSON支持:8.0增强了JSON功能
- 窗口函数:8.0支持窗口函数,便于复杂分析
- CTE(公共表表达式):8.0支持WITH子句
- 角色管理:8.0引入了更完善的RBAC支持
- 性能提升:8.0在读写性能、高并发方面有显著提升
18. 监控与维护
18.1 关键监控指标
- 查询性能:慢查询数量、平均查询时间
- 连接数:当前连接数、最大连接数
- 缓冲池使用情况
- 锁等待和死锁情况
- 复制延迟(如果使用主从复制)
18.2 常用维护命令
sql复制-- 查看运行状态
SHOW STATUS;
-- 查看进程列表
SHOW PROCESSLIST;
-- 查看变量设置
SHOW VARIABLES;
-- 刷新权限
FLUSH PRIVILEGES;
-- 刷新日志
FLUSH LOGS;
-- 关闭所有表并清除缓存
FLUSH TABLES;
19. 开发规范建议
-
命名规范:
- 数据库、表、字段名使用小写字母和下划线组合
- 避免使用MySQL保留字
- 名称应简洁且有意义
-
SQL编写规范:
- 关键字使用大写(如SELECT, INSERT等)
- 表名和字段名使用小写
- 适当使用缩进和换行增强可读性
- 为复杂查询添加注释
-
索引使用规范:
- 为常用查询条件创建索引
- 避免过度索引,特别是对频繁更新的表
- 定期检查并删除未使用的索引
-
事务规范:
- 事务应尽可能短小
- 避免在事务中进行耗时操作(如网络请求)
- 合理设置事务隔离级别
20. 学习资源推荐
- 官方文档:MySQL 8.0 Reference Manual
- 书籍:
- 《高性能MySQL》
- 《MySQL技术内幕》
- 《SQL必知必会》
- 在线课程:
- MySQL官方培训课程
- Coursera/慕课网等平台的数据库课程
- 实践工具:
- MySQL Workbench
- Percona Toolkit
- pt-query-digest
掌握MySQL核心SQL语句是数据库管理和开发的基础。从简单的CRUD操作到复杂的查询优化,需要不断实践和积累经验。建议在实际工作中多练习这些语句,并结合具体业务场景深入理解其应用。记住,良好的数据库设计和使用规范往往比单纯的技术更重要。