一、数据库操作
1.1 创建数据库
CREATE DATABASE 数据库名;
CREATE DATABASE school;
CREATE DATABASE mydb
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS school;
1.2 选择数据库
USE school;
SELECT DATABASE();
1.3 修改数据库
ALTER DATABASE school
CHARACTER SET utf8
COLLATE utf8_general_ci;
1.4 删除数据库
DROP DATABASE school;
DROP DATABASE IF EXISTS school;
二、表操作
2.1 MySQL数据类型
数值类型
| 类型 | 大小 | 范围 | 用途 |
|---|
| TINYINT | 1字节 | -128~127 | 小整数 |
| SMALLINT | 2字节 | -32768~32767 | 中等整数 |
| INT | 4字节 | -2147万~2147万 | 标准整数 |
| BIGINT | 8字节 | 非常大 | 大整数 |
| FLOAT | 4字节 | 单精度浮点数 | 小数 |
| DOUBLE | 8字节 | 双精度浮点数 | 精确小数 |
| DECIMAL(m,d) | 变长 | 精确小数 | 金额 |
字符串类型
| 类型 | 大小 | 用途 |
|---|
| CHAR(n) | 0-255字节 | 固定长度字符串 |
| VARCHAR(n) | 0-65535字节 | 可变长度字符串 |
| TEXT | 0-65535字节 | 长文本数据 |
| ENUM('值1','值2') | 1-2字节 | 枚举值 |
日期时间类型
| 类型 | 格式 | 范围 |
|---|
| 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 | 时间戳 | 1970-01-01~2038-01-19 |
| YEAR | YYYY | 1901~2155 |
2.2 创建表
CREATE TABLE 表名 (
列名1 数据类型 [约束],
列名2 数据类型 [约束],
...
);
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
student_no VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(50) NOT NULL,
gender ENUM('男', '女') DEFAULT '男',
age INT CHECK (age >= 0 AND age <= 100),
email VARCHAR(100),
phone VARCHAR(20),
address VARCHAR(200),
birthday DATE,
enrollment_date DATE DEFAULT (CURRENT_DATE),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE courses (
course_id INT PRIMARY KEY AUTO_INCREMENT,
course_code VARCHAR(20) UNIQUE NOT NULL,
course_name VARCHAR(100) NOT NULL,
credit DECIMAL(3,1) DEFAULT 1.0,
teacher VARCHAR(50),
class_hours INT DEFAULT 36
);
2.3 查看表信息
SHOW TABLES;
DESC students;
DESCRIBE students;
SHOW CREATE TABLE students;
2.4 修改表结构
ALTER TABLE students
ADD COLUMN major VARCHAR(50) AFTER name;
ALTER TABLE students
MODIFY COLUMN name VARCHAR(100) NOT NULL;
ALTER TABLE students
CHANGE COLUMN phone mobile VARCHAR(15);
ALTER TABLE students
DROP COLUMN address;
ALTER TABLE students
ADD PRIMARY KEY (id);
ALTER TABLE students
ADD UNIQUE (email);
ALTER TABLE scores
ADD FOREIGN KEY (student_id) REFERENCES students(id);
ALTER TABLE students
RENAME TO student_info;
RENAME TABLE students TO student_info;
2.5 删除表
DROP TABLE students;
DROP TABLE IF EXISTS students;
TRUNCATE TABLE students;
三、数据增删改查
3.1 插入数据 (INSERT)
INSERT INTO students (student_no, name, gender, age, email)
VALUES ('2023001', '张三', '男', 20, 'zhangsan@qq.com');
INSERT INTO students (student_no, name, gender, age) VALUES
('2023002', '李四', '女', 21),
('2023003', '王五', '男', 22),
('2023004', '赵六', '女', 19);
INSERT INTO students (student_no, name)
VALUES ('2023005', '孙七');
INSERT INTO students
SET student_no = '2023006',
name = '周八',
age = 23;
INSERT INTO new_students
SELECT * FROM students WHERE age > 20;
3.2 查询数据 (SELECT)
SELECT * FROM students;
SELECT id, name, age FROM students;
SELECT
id AS 学号,
name AS 姓名,
age AS 年龄
FROM students;
SELECT DISTINCT gender FROM students;
SELECT DISTINCT age, gender FROM students;
3.3 条件查询 (WHERE)
SELECT * FROM students WHERE age > 20;
SELECT * FROM students WHERE age >= 18;
SELECT * FROM students WHERE age < 22;
SELECT * FROM students WHERE age <= 21;
SELECT * FROM students WHERE age = 20;
SELECT * FROM students WHERE age != 20;
SELECT * FROM students WHERE age <> 20;
SELECT * FROM students WHERE age > 18 AND gender = '男';
SELECT * FROM students WHERE age < 20 OR gender = '女';
SELECT * FROM students WHERE NOT (age = 20);
SELECT * FROM students WHERE age BETWEEN 18 AND 22;
SELECT * FROM students WHERE age IN (18, 20, 22);
SELECT * FROM students WHERE age NOT IN (18, 20);
SELECT * FROM students WHERE name LIKE '张%';
SELECT * FROM students WHERE name LIKE '%三';
SELECT * FROM students WHERE name LIKE '%小%';
SELECT * FROM students WHERE name LIKE '张_';
SELECT * FROM students WHERE name NOT LIKE '张%';
SELECT * FROM students WHERE email IS NULL;
SELECT * FROM students WHERE email IS NOT NULL;
3.4 排序查询 (ORDER BY)
SELECT * FROM students ORDER BY age;
SELECT * FROM students ORDER BY age ASC;
SELECT * FROM students ORDER BY age DESC;
SELECT * FROM students
ORDER BY gender DESC, age ASC;
SELECT * FROM students
WHERE age > 18
ORDER BY age DESC;
3.5 限制查询 (LIMIT)
SELECT * FROM students LIMIT 5;
SELECT * FROM students LIMIT 10, 5;
SELECT * FROM students
ORDER BY age DESC
LIMIT 3;
3.6 更新数据 (UPDATE)
-- 更新所有行(谨慎使用)
UPDATE students SET age = age + 1
-- 条件更新
UPDATE students SET age = 21 WHERE name = '张三'
-- 更新多个字段
UPDATE students SET
age = 22,
email = 'lisi@163.com'
WHERE name = '李四'
-- 使用表达式
UPDATE students SET
age = age + 1,
updated_at = NOW()
WHERE birthday = '2000-01-01'
3.7 删除数据 (DELETE)
DELETE FROM students WHERE id = 5;
DELETE FROM students
WHERE age < 18 OR email IS NULL;
DELETE FROM students;
SELECT * FROM students WHERE id = 5;
DELETE FROM students WHERE id = 5;
四、查询进阶
4.1 聚合函数
SELECT COUNT(*) FROM students;
SELECT COUNT(email) FROM students;
SELECT COUNT(DISTINCT gender) FROM students;
SELECT AVG(age) FROM students;
SELECT AVG(age) AS 平均年龄 FROM students;
SELECT SUM(age) FROM students;
SELECT MAX(age) FROM students;
SELECT MIN(age) FROM students;
SELECT
COUNT(*) AS 总人数,
AVG(age) AS 平均年龄,
MAX(age) AS 最大年龄,
MIN(age) AS 最小年龄
FROM students;
4.2 分组查询 (GROUP BY)
SELECT gender, COUNT(*) AS 人数
FROM students
GROUP BY gender;
SELECT gender, AVG(age) AS 平均年龄
FROM students
GROUP BY gender
HAVING AVG(age) > 20;
SELECT gender, major, COUNT(*) AS 人数
FROM students
GROUP BY gender, major;
SELECT gender, COUNT(*) AS 人数
FROM students
GROUP BY gender
ORDER BY 人数 DESC;
4.3 连接查询 (JOIN)
创建关联表
CREATE TABLE scores (
score_id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT,
course_id INT,
score DECIMAL(5,2),
exam_date DATE,
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(course_id)
);
内连接 (INNER JOIN)
-- 查询学生及成绩
SELECT
s.name AS 学生姓名,
c.course_name AS 课程名称,
sc.score AS 成绩
FROM students s
INNER JOIN scores sc ON s.id = sc.student_id
INNER JOIN courses c ON sc.course_id = c.course_id;
-- 简化写法
SELECT
s.name, c.course_name, sc.score
FROM students s, scores sc, courses c
WHERE s.id = sc.student_id
AND sc.course_id = c.course_id;
左连接 (LEFT JOIN)
-- 查询所有学生(包括没有成绩的)
SELECT
s.name AS 学生姓名,
sc.score AS 成绩
FROM students s
LEFT JOIN scores sc ON s.id = sc.student_id;
右连接 (RIGHT JOIN)
-- 查询所有课程(包括没有学生的)
SELECT
c.course_name AS 课程名称,
sc.score AS 成绩
FROM scores sc
RIGHT JOIN courses c ON sc.course_id = c.course_id;
4.4 子查询
SELECT * FROM students
WHERE age > (SELECT AVG(age) FROM students);
SELECT * FROM students
WHERE id IN (SELECT student_id FROM scores WHERE score > 90);
SELECT
name,
age,
(SELECT AVG(age) FROM students) AS 平均年龄
FROM students;
SELECT * FROM students s
WHERE EXISTS (
SELECT 1 FROM scores sc
WHERE sc.student_id = s.id AND sc.score > 95
);
4.5 联合查询 (UNION)
SELECT name, '学生' AS 类型 FROM students
UNION
SELECT teacher, '教师' AS 类型 FROM courses;
SELECT name FROM students WHERE gender = '男'
UNION ALL
SELECT name FROM students WHERE age > 20;
五、数据完整性
5.1 约束类型
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
age INT CHECK (age >= 18 AND age <= 65),
status VARCHAR(20) DEFAULT 'active',
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
5.2 索引优化
CREATE INDEX idx_name ON students(name);
CREATE INDEX idx_age_gender ON students(age, gender);
CREATE UNIQUE INDEX idx_email ON students(email);
SHOW INDEX FROM students;
DROP INDEX idx_name ON students;
SELECT * FROM students WHERE name = '张三';
SELECT * FROM students WHERE age > 20 AND gender = '男';
SELECT * FROM students ORDER BY name;
SELECT * FROM students WHERE age + 1 > 20;
SELECT * FROM students WHERE name LIKE '%三%';
六、实战练习
6.1 学生管理系统完整示例
CREATE DATABASE school_system;
USE school_system;
CREATE TABLE departments (
dept_id INT PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(50) NOT NULL UNIQUE,
dean VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE majors (
major_id INT PRIMARY KEY AUTO_INCREMENT,
major_name VARCHAR(50) NOT NULL,
dept_id INT,
duration INT DEFAULT 4,
FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);
CREATE TABLE classes (
class_id INT PRIMARY KEY AUTO_INCREMENT,
class_name VARCHAR(50) NOT NULL,
major_id INT,
counselor VARCHAR(50),
student_count INT DEFAULT 0,
FOREIGN KEY (major_id) REFERENCES majors(major_id)
);
ALTER TABLE students
ADD COLUMN class_id INT,
ADD COLUMN enrollment_year YEAR,
ADD FOREIGN KEY (class_id) REFERENCES classes(class_id);
INSERT INTO departments (dept_name, dean) VALUES
('计算机学院', '张教授'),
('经济学院', '李教授');
INSERT INTO majors (major_name, dept_id) VALUES
('计算机科学与技术', 1),
('软件工程', 1),
('经济学', 2);
SELECT
d.dept_name AS 院系,
COUNT(s.id) AS 学生人数
FROM departments d
LEFT JOIN majors m ON d.dept_id = m.dept_id
LEFT JOIN classes c ON m.major_id = c.major_id
LEFT JOIN students s ON c.class_id = s.class_id
GROUP BY d.dept_id;
SELECT
c.course_name AS 课程,
AVG(sc.score) AS 平均分,
COUNT(sc.score) AS 考试人数
FROM courses c
LEFT JOIN scores sc ON c.course_id = sc.course_id
GROUP BY c.course_id
HAVING COUNT(sc.score) > 0
ORDER BY 平均分 DESC;
6.2 常用实用查询模板
SELECT * FROM table_name
WHERE conditions
ORDER BY column_name
LIMIT (page_num - 1) * page_size, page_size;
SELECT
DATE_FORMAT(date_column, '%Y-%m') AS 月份,
COUNT(*) AS 总数,
SUM(amount) AS 总额,
AVG(amount) AS 平均值
FROM table_name
WHERE date_column BETWEEN '2023-01-01' AND '2023-12-31'
GROUP BY DATE_FORMAT(date_column, '%Y-%m')
ORDER BY 月份;
SELECT EXISTS(
SELECT 1 FROM students
WHERE student_no = '2023001'
) AS 是否存在;
SELECT * FROM students
ORDER BY RAND()
LIMIT 1;
七、故障处理
7.1 常见错误及解决
连接错误
ERROR 1045 (28000): Access denied for user
解决:检查用户名密码,或重置密码
数据库不存在
ERROR 1049 (42000): Unknown database 'database_name'
解决:CREATE DATABASE 先创建数据库
表不存在
ERROR 1146 (42S02): Table doesn
解决:检查表名拼写,或创建表
语法错误
ERROR 1064 (42000): You have an error in your SQL syntax
解决:检查SQL语句,特别注意引号、逗号
外键约束错误
ERROR 1452 (23000): Cannot add or update a child row
解决:先插入主表数据,再插入从表数据
7.2 备份与恢复
# 备份单个数据库
mysqldump -u root -p school > backup.sql
# 备份所有数据库
mysqldump -u root -p --all-databases > all_backup.sql
# 备份指定表
mysqldump -u root -p school students courses > tables_backup.sql
# 恢复数据库
mysql -u root -p school < backup.sql
# 压缩备份
mysqldump -u root -p school | gzip > backup.sql.gz
# 解压恢复
gunzip < backup.sql.gz | mysql -u root -p school
7.3 性能优化建议
- 设计时优化
-
- 选择合适的数据类型
- 规范化表结构(但不要过度)
- 为经常查询的列创建索引
- 查询时优化
-
- 避免 SELECT *
- 使用 LIMIT 限制结果
- 避免在 WHERE 子句中使用函数
- 使用 EXPLAIN 分析查询
- 维护建议
-
- 定期优化表:
OPTIMIZE TABLE table_name;
- 定期分析表:
ANALYZE TABLE table_name;
- 监控慢查询日志
SHOW PROCESSLIST;
KILL process_id;
SHOW VARIABLES LIKE '%timeout%';
SHOW STATUS LIKE 'Connections';
八、快速参考
8.1 常用命令速查
| 操作 | 命令 |
|---|
| 登录 | mysql -u root -p |
| 查看数据库 | SHOW DATABASES; |
| 使用数据库 | USE database_name; |
| 查看表 | SHOW TABLES; |
| 查看表结构 | DESC table_name; |
| 退出 | EXIT; 或 \q |
8.2 数据类型选择指南
| 存储内容 | 推荐类型 |
|---|
| 用户ID | INT UNSIGNED AUTO_INCREMENT |
| 用户名 | VARCHAR(50) |
| 密码哈希 | CHAR(60) (bcrypt) |
| 邮箱 | VARCHAR(100) |
| 手机号 | VARCHAR(20) |
| 金额 | DECIMAL(10,2) |
| 文章内容 | TEXT 或 LONGTEXT |
| 是否启用 | TINYINT(1) 或 BOOLEAN |
| 创建时间 | TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
| 更新时间 | TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
8.3 最佳实践清单
命名规范
- ✅ 数据库名:小写,下划线分隔(如:
school_db)
- ✅ 表名:复数形式,小写(如:
students)
- ✅ 列名:小写,下划线分隔(如:
created_at)
- ❌ 避免使用MySQL保留字
- ❌ 避免使用特殊字符
设计原则
- ✅ 每列不可再分(第一范式)
- ✅ 每个表必须有主键
- ✅ 适当使用外键保持数据完整性
- ✅ 考虑查询频率创建索引
- ❌ 避免过度规范化
- ❌ 避免存储大对象在数据库
安全建议
- ✅ 定期备份数据(至少每天一次)
- ✅ 生产环境使用专用账号,不用root
- ✅ 应用程序使用只读/只写账号
- ✅ 密码加密存储(不用明文)
- ✅ 限制远程访问IP
- ❌ 不要在代码中写死密码
性能优化
- ✅ 为频繁查询的列创建索引
- ✅ 查询时使用具体的列名,避免SELECT *
- ✅ 合理使用LIMIT限制返回结果
- ✅ 定期清理无用数据
- ❌ 避免在WHERE子句中使用函数
- ❌ 避免使用前导通配符的LIKE查询
8.4 实用代码片段
快速创建测试表
CREATE TABLE test_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
age INT DEFAULT 18,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
常用日期查询
SELECT * FROM orders WHERE DATE(order_date) = CURDATE();
SELECT * FROM orders WHERE DATE(order_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY);
SELECT * FROM orders WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY);
SELECT * FROM orders
WHERE MONTH(order_date) = MONTH(CURDATE())
AND YEAR(order_date) = YEAR(CURDATE());
数据导出导入
-- 导出查询结果到文件
SELECT * INTO OUTFILE
FIELDS TERMINATED BY
ENCLOSED BY
LINES TERMINATED BY
FROM students;
-- 从文件导入数据
LOAD DATA INFILE
INTO TABLE students
FIELDS TERMINATED BY
ENCLOSED BY
LINES TERMINATED BY