MySQL是世界上最流行的开源关系型数据库,几乎所有中小型网站都在使用。无论是做Web开发、数据分析还是后端架构,掌握MySQL都是一项必备技能。本教程从零基础讲起,带你掌握MySQL的核心用法。

一、数据库基础概念

二、数据库操作

-- 创建数据库 CREATE DATABASE IF NOT EXISTS myapp DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; -- 查看所有数据库 SHOW DATABASES; -- 使用数据库 USE myapp; -- 删除数据库(谨慎操作) DROP DATABASE IF EXISTS myapp;

三、数据表设计

-- 创建用户表 CREATE TABLE users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, age TINYINT UNSIGNED DEFAULT 0, status ENUM('active', 'inactive', 'banned') DEFAULT 'active', avatar VARCHAR(255) DEFAULT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_email (email), INDEX idx_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建文章表 CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id INT UNSIGNED NOT NULL, title VARCHAR(200) NOT NULL, content TEXT, view_count INT UNSIGNED DEFAULT 0, published_at DATETIME DEFAULT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, INDEX idx_user (user_id), INDEX idx_published (published_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

四、CRUD操作

插入数据(Create)

-- 单条插入 INSERT INTO users (username, email, password_hash, age) VALUES ('zhangsan', 'zhangsan@example.com', 'hash_value', 25); -- 批量插入 INSERT INTO users (username, email, password_hash, age) VALUES ('lisi', 'lisi@example.com', 'hash2', 28), ('wangwu', 'wangwu@example.com', 'hash3', 22), ('zhaoliu', 'zhaoliu@example.com', 'hash4', 30);

查询数据(Read)

-- 基础查询 SELECT * FROM users WHERE status = 'active' LIMIT 10; -- 条件查询 SELECT username, email, age FROM users WHERE age BETWEEN 20 AND 30 ORDER BY age DESC; -- 模糊查询 SELECT * FROM users WHERE username LIKE '%张%'; -- 聚合查询 SELECT status, COUNT(*) as count, AVG(age) as avg_age, MAX(age) as max_age FROM users GROUP BY status; -- 连表查询(JOIN) SELECT u.username, a.title, a.view_count FROM users u INNER JOIN articles a ON u.id = a.user_id WHERE a.published_at IS NOT NULL ORDER BY a.view_count DESC LIMIT 20; -- 子查询 SELECT * FROM users WHERE id IN ( SELECT user_id FROM articles WHERE view_count > 1000 );

更新数据(Update)

-- 更新单条记录 UPDATE users SET age = 26 WHERE id = 1; -- 批量更新 UPDATE users SET status = 'inactive' WHERE created_at < '2025-01-01' AND status = 'active'; -- 更新时关联其他表 UPDATE articles a INNER JOIN users u ON a.user_id = u.id SET a.view_count = a.view_count + 1 WHERE u.username = 'zhangsan';

删除数据(Delete)

-- 删除单条 DELETE FROM users WHERE id = 1; -- 按条件删除 DELETE FROM users WHERE status = 'banned' AND created_at < '2024-01-01'; -- 清空表(保留表结构) TRUNCATE TABLE articles;

五、索引优化

索引是提升查询性能的关键手段,合理使用索引可以让查询速度提升数十倍甚至更多。

-- 创建普通索引 CREATE INDEX idx_email ON users(email); -- 创建唯一索引 CREATE UNIQUE INDEX idx_username ON users(username); -- 创建复合索引(最左匹配原则) CREATE INDEX idx_status_age ON users(status, age); -- 查看索引使用情况 SHOW INDEX FROM users; -- 使用EXPLAIN分析查询 EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
索引使用原则:频繁查询的字段加索引,区分度高的字段加索引,WHERE/JOIN/ORDER BY中的字段考虑加索引。但不要过度使用索引,每个索引都会增加写入开销和存储空间。

六、事务处理

-- 开启事务 START TRANSACTION; -- 执行操作(转账示例) UPDATE users SET balance = balance - 100 WHERE id = 1; UPDATE users SET balance = balance + 100 WHERE id = 2; -- 提交事务 COMMIT; -- 如果出错,回滚 -- ROLLBACK;

七、性能优化建议

  1. 避免 SELECT *:只查询需要的字段,减少数据传输量
  2. 合理使用索引:WHERE、ORDER BY、GROUP BY 的字段适当加索引
  3. 使用分页查询:大表查询使用 LIMIT + OFFSET 或游标分页
  4. 避免在WHERE中使用函数:WHERE YEAR(created_at) = 2026 会索引失效
  5. 适当使用缓存:高频读取的数据可以用Redis缓存
  6. 定期优化表:使用 OPTIMIZE TABLE 命令整理碎片

八、表设计实战:博客系统

-- 用户表 CREATE TABLE users ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, avatar VARCHAR(255) DEFAULT '', status TINYINT DEFAULT 1 COMMENT '1正常 0禁用', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_username (username) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 文章表 CREATE TABLE articles ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, title VARCHAR(200) NOT NULL, content TEXT NOT NULL, category VARCHAR(50) DEFAULT '未分类', status TINYINT DEFAULT 1 COMMENT '1已发布 0草稿', view_count INT DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_user_id (user_id), INDEX idx_category (category), INDEX idx_created (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 查询某个用户的所有已发布文章,按时间倒序 SELECT a.id, a.title, a.category, a.view_count, a.created_at FROM articles a WHERE a.user_id = 1 AND a.status = 1 ORDER BY a.created_at DESC LIMIT 20;

九、常见SQL面试题

-- 1. 查询每个分类的文章数量 SELECT category, COUNT(*) as total FROM articles WHERE status = 1 GROUP BY category ORDER BY total DESC; -- 2. 查询文章数最多的用户 SELECT u.username, COUNT(a.id) as article_count FROM users u LEFT JOIN articles a ON u.id = a.user_id AND a.status = 1 GROUP BY u.id ORDER BY article_count DESC LIMIT 1; -- 3. 查询最近7天每天都有发文章的用户 SELECT user_id, COUNT(DISTINCT DATE(created_at)) as days FROM articles WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY user_id HAVING days = 7;
总结:MySQL是后端开发的基石。新手先掌握增删改查和索引,再逐步学习事务、锁、分库分表。建议用 EXPLAIN 分析慢查询,是优化的第一步。