1. MySQL基础操作概述
MySQL作为最流行的关系型数据库管理系统之一,掌握其基础操作是每位开发者的必备技能。本文将全面介绍MySQL中的增删查改(CRUD)操作,从数据库和表的基本操作到数据的各种查询和修改技巧,帮助读者快速上手MySQL数据库操作。
作为一名有着多年数据库开发经验的工程师,我深知在实际项目中,熟练的SQL操作能力能极大提升开发效率。本文将结合我的实战经验,不仅介绍基础语法,还会分享一些实际开发中的技巧和注意事项。
2. 数据库操作
2.1 创建数据库
创建数据库是使用MySQL的第一步,语法如下:
sql复制CREATE DATABASE [IF NOT EXISTS] 数据库名
[CHARACTER SET 字符集]
[COLLATE 校验规则];
其中:
IF NOT EXISTS:可选参数,表示如果数据库不存在则创建CHARACTER SET:指定数据库字符集,如utf8、gbk等COLLATE:指定校验规则,如utf8_general_ci
实际案例:
sql复制-- 创建默认字符集的数据库
CREATE DATABASE mydb;
-- 创建指定字符集的数据库
CREATE DATABASE mydb2 CHARACTER SET gbk COLLATE gbk_bin;
注意:如果不指定字符集和校验规则,MySQL会使用默认配置(通常为utf8和utf8_general_ci)
2.2 查看数据库信息
查看当前MySQL实例中的所有数据库:
sql复制SHOW DATABASES;
查看特定数据库的创建语句:
sql复制SHOW CREATE DATABASE 数据库名;
这个命令会显示数据库的完整创建语句,包括字符集和校验规则设置,对于数据库迁移和复制非常有用。
2.3 修改数据库
MySQL允许修改数据库的字符集和校验规则:
sql复制ALTER DATABASE 数据库名
[CHARACTER SET 字符集]
[COLLATE 校验规则];
例如:
sql复制ALTER DATABASE mydb CHARACTER SET gbk COLLATE gbk_bin;
重要限制:MySQL不支持直接修改数据库名,如需重命名数据库,需要先导出数据再导入到新数据库
2.4 删除数据库
删除数据库的语法:
sql复制DROP DATABASE [IF EXISTS] 数据库名;
例如:
sql复制DROP DATABASE IF EXISTS mydb;
警告:删除数据库会同时删除该数据库中的所有表和数据,操作不可逆,请谨慎执行
2.5 数据库备份与恢复
2.5.1 备份数据库
使用mysqldump工具备份数据库:
bash复制mysqldump -P 端口号 -u 用户名 -p 密码 -B 数据库名 > 备份文件路径
例如:
bash复制mysqldump -P 3306 -u root -p123456 -B mydb > /backup/mydb.sql
2.5.2 恢复数据库
在MySQL命令行中执行:
sql复制SOURCE 备份文件路径;
例如:
sql复制SOURCE /backup/mydb.sql;
技巧:备份时加上
-B参数会在备份文件中包含创建数据库的语句,恢复时更方便
2.5.3 表级备份与恢复
备份特定表:
bash复制mysqldump -P 端口号 -u 用户名 -p 密码 数据库名 表名1 表名2 > 备份文件路径
恢复表:
sql复制SOURCE 备份文件路径;
3. 表操作
3.1 创建表
创建表的基本语法:
sql复制CREATE TABLE 表名 (
列名1 数据类型 [约束] [COMMENT '注释'],
列名2 数据类型 [约束] [COMMENT '注释'],
...
) [ENGINE=存储引擎] [CHARSET=字符集] [COLLATE=校验规则];
例如:
sql复制CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL COMMENT '学生姓名',
age TINYINT UNSIGNED,
gender ENUM('男','女'),
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8mb4;
注意:如果不指定存储引擎,默认使用InnoDB;不指定字符集则继承数据库的字符集设置
3.2 查看表结构
查看表的基本结构:
sql复制DESC 表名;
查看表的详细创建语句:
sql复制SHOW CREATE TABLE 表名\G
\G参数可以使结果垂直显示,便于阅读宽表结构。
3.3 修改表结构
3.3.1 添加列
sql复制ALTER TABLE 表名 ADD 列名 数据类型 [约束] [AFTER 列名|FIRST];
例如:
sql复制-- 在最后添加列
ALTER TABLE student ADD email VARCHAR(50);
-- 在指定列后添加
ALTER TABLE student ADD phone VARCHAR(20) AFTER name;
-- 添加到第一列
ALTER TABLE student ADD sno VARCHAR(10) FIRST;
3.3.2 修改列
sql复制ALTER TABLE 表名 MODIFY 列名 新数据类型 [新约束];
例如:
sql复制ALTER TABLE student MODIFY name VARCHAR(30) NOT NULL;
3.3.3 重命名列
sql复制ALTER TABLE 表名 CHANGE 旧列名 新列名 数据类型 [约束];
例如:
sql复制ALTER TABLE student CHANGE gender sex ENUM('男','女');
3.3.4 删除列
sql复制ALTER TABLE 表名 DROP 列名;
例如:
sql复制ALTER TABLE student DROP sno;
3.3.5 重命名表
sql复制ALTER TABLE 旧表名 RENAME TO 新表名;
或者:
sql复制RENAME TABLE 旧表名 TO 新表名;
3.4 删除表
删除表结构:
sql复制DROP TABLE [IF EXISTS] 表名;
清空表数据(保留表结构):
sql复制DELETE FROM 表名;
或者:
sql复制TRUNCATE TABLE 表名;
区别:TRUNCATE比DELETE更快,且会重置自增ID,但无法回滚
4. 数据操作
4.1 插入数据
4.1.1 基本插入
sql复制INSERT INTO 表名 [(列名1, 列名2, ...)]
VALUES (值1, 值2, ...), (值1, 值2, ...), ...;
例如:
sql复制-- 全列插入
INSERT INTO student VALUES
(1, '张三', 20, '男', 'zhangsan@example.com', '13800138000', NOW()),
(2, '李四', 21, '女', 'lisi@example.com', '13800138001', NOW());
-- 指定列插入
INSERT INTO student (name, age, sex) VALUES
('王五', 22, '男'),
('赵六', 23, '女');
4.1.2 插入否则更新
当插入数据可能引发主键或唯一键冲突时:
sql复制INSERT INTO 表名 [(列名1, 列名2, ...)]
VALUES (值1, 值2, ...)
ON DUPLICATE KEY UPDATE 列名1=值1, 列名2=值2, ...;
例如:
sql复制INSERT INTO student (id, name, age)
VALUES (1, '张三三', 25)
ON DUPLICATE KEY UPDATE name='张三三', age=25;
4.1.3 插入查询结果
sql复制INSERT INTO 表名 [(列名1, 列名2, ...)]
SELECT ...;
例如,将成绩优秀的学生复制到优秀学生表:
sql复制INSERT INTO excellent_student (id, name, score)
SELECT id, name, score FROM student WHERE score >= 90;
4.2 查询数据
4.2.1 基本查询
sql复制SELECT 列名1, 列名2, ... FROM 表名 [WHERE 条件];
例如:
sql复制-- 全列查询
SELECT * FROM student;
-- 指定列查询
SELECT id, name, age FROM student;
-- 带条件查询
SELECT * FROM student WHERE age > 20;
4.2.2 表达式查询
sql复制SELECT 表达式 [AS 别名] FROM 表名;
例如:
sql复制-- 计算总分
SELECT name, chinese + math + english AS total FROM exam_result;
-- 使用函数
SELECT name, UPPER(name) AS upper_name FROM student;
4.2.3 去重查询
sql复制SELECT DISTINCT 列名 FROM 表名;
例如:
sql复制-- 查询不重复的年龄
SELECT DISTINCT age FROM student;
4.2.4 条件查询
WHERE子句支持多种条件运算符:
- 比较运算符:=, !=, >, >=, <, <=
- 逻辑运算符:AND, OR, NOT
- BETWEEN...AND...
- IN (值1, 值2, ...)
- IS NULL / IS NOT NULL
- LIKE 通配符匹配
例如:
sql复制-- 多条件查询
SELECT * FROM student
WHERE age BETWEEN 20 AND 22
AND sex = '男';
-- NULL值查询
SELECT * FROM student WHERE email IS NULL;
-- 模糊查询
SELECT * FROM student WHERE name LIKE '张%';
4.2.5 排序查询
sql复制SELECT ... FROM 表名
ORDER BY 列名1 [ASC|DESC], 列名2 [ASC|DESC], ...;
例如:
sql复制-- 单列排序
SELECT * FROM student ORDER BY age DESC;
-- 多列排序
SELECT * FROM exam_result
ORDER BY chinese DESC, math DESC, english DESC;
4.2.6 分页查询
sql复制SELECT ... FROM 表名
LIMIT 数量 [OFFSET 偏移量];
或者:
sql复制SELECT ... FROM 表名
LIMIT [偏移量,] 数量;
例如:
sql复制-- 第一页,每页10条
SELECT * FROM student LIMIT 10;
-- 第二页
SELECT * FROM student LIMIT 10 OFFSET 10;
-- 等价于
SELECT * FROM student LIMIT 10, 10;
4.2.7 聚合查询
常用聚合函数:
- COUNT() - 计数
- SUM() - 求和
- AVG() - 平均值
- MAX() - 最大值
- MIN() - 最小值
例如:
sql复制-- 统计学生总数
SELECT COUNT(*) FROM student;
-- 计算平均年龄
SELECT AVG(age) FROM student;
-- 分组统计
SELECT sex, COUNT(*) AS count, AVG(age) AS avg_age
FROM student
GROUP BY sex;
4.2.8 分组查询
GROUP BY子句用于对结果集进行分组:
sql复制SELECT 列名1, 列名2, ..., 聚合函数
FROM 表名
[WHERE 条件]
GROUP BY 列名1, 列名2, ...
[HAVING 分组条件];
例如:
sql复制-- 按性别统计平均年龄
SELECT sex, AVG(age) AS avg_age
FROM student
GROUP BY sex;
-- 筛选分组结果
SELECT dept, AVG(salary) AS avg_salary
FROM employee
GROUP BY dept
HAVING AVG(salary) > 5000;
注意:WHERE在分组前过滤,HAVING在分组后过滤
4.3 更新数据
sql复制UPDATE 表名
SET 列名1=值1, 列名2=值2, ...
[WHERE 条件]
[ORDER BY 列名]
[LIMIT 数量];
例如:
sql复制-- 更新单个记录
UPDATE student SET age = 23 WHERE id = 1;
-- 批量更新
UPDATE student SET status = 'active' WHERE age >= 20;
-- 带排序和限制的更新
UPDATE exam_result
SET math = math + 10
ORDER BY math ASC
LIMIT 5;
4.4 删除数据
sql复制DELETE FROM 表名
[WHERE 条件]
[ORDER BY 列名]
[LIMIT 数量];
例如:
sql复制-- 删除单个记录
DELETE FROM student WHERE id = 1;
-- 批量删除
DELETE FROM student WHERE age < 18;
-- 清空表
DELETE FROM student;
注意:DELETE是逐行删除,TRUNCATE是直接删除表并重建,后者效率更高但无法回滚
5. 高级技巧与注意事项
5.1 事务处理
MySQL默认自动提交事务,可以显式使用事务:
sql复制START TRANSACTION;
-- 执行SQL语句
COMMIT; -- 或 ROLLBACK;
例如:
sql复制START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;
COMMIT;
5.2 索引使用
创建索引提高查询效率:
sql复制-- 创建普通索引
CREATE INDEX idx_name ON student(name);
-- 创建唯一索引
CREATE UNIQUE INDEX idx_email ON student(email);
-- 查看索引
SHOW INDEX FROM student;
提示:索引虽然能加速查询,但会降低写入速度,需合理使用
5.3 外键约束
创建带外键的表:
sql复制CREATE TABLE score (
id INT PRIMARY KEY,
student_id INT,
course VARCHAR(50),
score INT,
FOREIGN KEY (student_id) REFERENCES student(id)
);
5.4 性能优化建议
- 避免使用SELECT *,只查询需要的列
- 为常用查询条件创建索引
- 合理使用EXPLAIN分析查询执行计划
- 批量操作使用事务减少IO开销
- 大表分页避免使用LIMIT offset, size,改用WHERE id > last_id LIMIT size
5.5 常见问题解决
- 中文乱码问题:确保连接、数据库、表和字段的字符集一致(推荐utf8mb4)
- 时间格式问题:使用标准格式'YYYY-MM-DD HH:MM:SS'
- 主键冲突:使用ON DUPLICATE KEY UPDATE或REPLACE INTO
- 性能瓶颈:使用慢查询日志定位问题SQL
6. 实战经验分享
在实际项目中,我发现以下几点特别重要:
-
设计合理的表结构:良好的数据库设计是高效查询的基础,遵循范式但不要过度设计
-
使用预处理语句:防止SQL注入,提高性能
sql复制PREPARE stmt FROM 'SELECT * FROM student WHERE id = ?';
SET @id = 1;
EXECUTE stmt USING @id;
DEALLOCATE PREPARE stmt;
-
定期维护数据库:优化表、备份数据、监控性能
-
合理使用存储过程和触发器:将复杂逻辑放在数据库端
-
掌握EXPLAIN的使用:了解查询执行计划,优化慢查询
最后提醒,数据库操作在生产环境要格外小心,特别是UPDATE和DELETE语句,建议:
- 先使用SELECT验证WHERE条件
- 在事务中执行,便于回滚
- 重要操作前备份数据