MySQL核心操作
在掌握了MySQL的基础知识后,我们现在来学习如何对数据库中的数据进行操作。这包括数据的插入、更新、删除以及查询等核心操作,这些是数据库管理的核心技能。
数据操纵语言(DML)
数据操纵语言(DML)用于操作数据库中的数据,主要包括插入、更新和删除数据的操作。
插入数据
向表中插入数据是数据库操作中最常见的任务之一。MySQL提供了多种插入数据的方式。
单条插入
最基本的插入操作是向表中插入单行数据:
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);示例:
-- 向students表插入一条记录
INSERT INTO students (student_id, name, gender, birth_date, phone, email)
VALUES ('2021001', '张三', '男', '2003-05-15', '13800138001', 'zhangsan@example.com');
-- 向courses表插入一条记录
INSERT INTO courses (course_code, course_name, credits, teacher, description)
VALUES ('CS101', '计算机科学导论', 3, '李教授', '计算机科学的基础课程');注意:
- 列名是可选的,但如果省略,必须为表中的所有列提供值
- 字符串值需要用单引号或双引号括起来
- 日期值应使用正确的日期格式
批量插入
为了提高效率,可以一次插入多行数据:
INSERT INTO table_name (column1, column2, column3, ...)
VALUES
(value1_1, value2_1, value3_1, ...),
(value1_2, value2_2, value3_2, ...),
(value1_3, value2_3, value3_3, ...);示例:
-- 批量插入学生记录
INSERT INTO students (student_id, name, gender, birth_date, phone, email)
VALUES
('2021002', '李四', '女', '2002-08-20', '13800138002', 'lisi@example.com'),
('2021003', '王五', '男', '2003-12-10', '13800138003', 'wangwu@example.com'),
('2021004', '赵六', '女', '2002-03-25', '13800138004', 'zhaoliu@example.com');
-- 批量插入课程记录
INSERT INTO courses (course_code, course_name, credits, teacher)
VALUES
('MATH101', '高等数学', 4, '张教授'),
('ENG101', '大学英语', 2, '王老师'),
('PHYS101', '大学物理', 3, '李教授');插入查询结果
还可以将一个查询的结果插入到另一个表中:
INSERT INTO target_table (column1, column2, ...)
SELECT column1, column2, ...
FROM source_table
WHERE condition;示例:
-- 创建一个临时表来存储优秀学生
CREATE TABLE excellent_students (
id INT AUTO_INCREMENT PRIMARY KEY,
student_id VARCHAR(20),
name VARCHAR(50),
avg_grade DECIMAL(5,2)
);
-- 将平均成绩大于85的学生插入到优秀学生表中
INSERT INTO excellent_students (student_id, name, avg_grade)
SELECT s.student_id, s.name, AVG(e.grade) as avg_grade
FROM students s
JOIN enrollments e ON s.id = e.student_id
GROUP BY s.id, s.student_id, s.name
HAVING AVG(e.grade) > 85;更新数据
更新数据用于修改表中已存在的记录。
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;示例:
-- 更新单个学生的邮箱
UPDATE students
SET email = 'zhangsan_new@example.com'
WHERE student_id = '2021001';
-- 更新多个字段
UPDATE courses
SET credits = 4, teacher = '陈教授'
WHERE course_code = 'CS101';
-- 更新满足条件的多条记录
UPDATE students
SET status = '毕业'
WHERE enrollment_date < '2020-01-01';
-- 使用表达式更新数据
UPDATE enrollments
SET grade = grade * 1.05 -- 给所有成绩增加5%
WHERE grade IS NOT NULL;重要提示:
- 永远不要忘记WHERE子句:如果没有WHERE子句,UPDATE语句会更新表中的所有记录!
- 在执行UPDATE之前,最好先用SELECT语句检查WHERE条件是否正确。
删除数据
删除数据用于从表中移除记录。
DELETE语句
DELETE语句逐行删除满足条件的记录:
DELETE FROM table_name WHERE condition;示例:
-- 删除特定学生
DELETE FROM students WHERE student_id = '2021001';
-- 删除满足条件的多条记录
DELETE FROM enrollments WHERE grade < 60;
-- 删除所有记录(但保留表结构)
DELETE FROM temp_table;TRUNCATE语句
TRUNCATE语句用于清空整个表,比DELETE更快,但有一些重要区别:
TRUNCATE TABLE table_name;示例:
-- 清空临时表
TRUNCATE TABLE temp_data;DELETE和TRUNCATE的主要区别:
- 速度:TRUNCATE比DELETE快
- 事务:TRUNCATE不能回滚(在某些存储引擎中)
- 触发器:TRUNCATE不会触发DELETE触发器
- 自增ID:TRUNCATE会重置自增ID为初始值
重要提示:
- 谨慎使用TRUNCATE:它会删除表中的所有数据且无法恢复
- 永远不要忘记WHERE子句:DELETE语句没有WHERE子句会删除所有记录
约束
约束用于确保数据的完整性和一致性。
主键约束(PRIMARY KEY)
主键约束确保表中的每一行都有唯一的标识符:
-- 在创建表时定义主键
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL
);
-- 在修改表时添加主键
ALTER TABLE temp_table ADD PRIMARY KEY (id);非空约束(NOT NULL)
非空约束确保字段不能为空:
-- 在创建表时定义非空约束
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL, -- 产品名称不能为空
price DECIMAL(10,2) NOT NULL -- 价格不能为空
);唯一约束(UNIQUE)
唯一约束确保字段中的值是唯一的:
-- 在创建表时定义唯一约束
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE, -- 用户名必须唯一
email VARCHAR(100) UNIQUE -- 邮箱必须唯一
);
-- 在修改表时添加唯一约束
ALTER TABLE students ADD UNIQUE (student_id);默认值约束(DEFAULT)
默认值约束为字段指定默认值:
-- 在创建表时定义默认值
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
order_date DATE DEFAULT (CURRENT_DATE), -- 默认为当前日期
status VARCHAR(20) DEFAULT '待处理', -- 默认状态
amount DECIMAL(10,2) DEFAULT 0.00 -- 默认金额为0
);外键约束(FOREIGN KEY)
外键约束用于建立表之间的关系:
-- 在创建表时定义外键
CREATE TABLE enrollments (
id INT AUTO_INCREMENT PRIMARY KEY,
student_id INT,
course_id INT,
grade DECIMAL(5,2),
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
-- 在修改表时添加外键
ALTER TABLE enrollments
ADD CONSTRAINT fk_student
FOREIGN KEY (student_id) REFERENCES students(id);数据查询语言(DQL)基础
数据查询语言(DQL)主要用于从数据库中检索数据,SELECT语句是DQL的核心。
基本查询
最基本的SELECT语句用于从表中检索数据:
-- 查询所有列
SELECT * FROM table_name;
-- 查询指定列
SELECT column1, column2, column3 FROM table_name;
-- 查询并指定别名
SELECT column1 AS alias1, column2 AS alias2 FROM table_name;示例:
-- 查询所有学生信息
SELECT * FROM students;
-- 查询学生的姓名和邮箱
SELECT name, email FROM students;
-- 查询并使用别名
SELECT name AS 学生姓名, email AS 邮箱地址 FROM students;条件查询
使用WHERE子句可以根据条件筛选数据:
SELECT column_list
FROM table_name
WHERE condition;常见的比较操作符:
=:等于!=或<>:不等于>:大于<:小于>=:大于等于<=:小于等于BETWEEN:在某个范围内IN:在某个列表中LIKE:模式匹配IS NULL:为空IS NOT NULL:不为空
示例:
-- 查询特定ID的学生
SELECT * FROM students WHERE student_id = '2021001';
-- 查询年龄大于20的学生
SELECT * FROM students WHERE age > 20;
-- 查询在指定范围内的学生
SELECT * FROM students WHERE age BETWEEN 18 AND 25;
-- 查询特定专业的学生
SELECT * FROM students WHERE major IN ('计算机科学', '软件工程');
-- 模糊查询(查找姓张的学生)
SELECT * FROM students WHERE name LIKE '张%';
-- 查询邮箱不为空的学生
SELECT * FROM students WHERE email IS NOT NULL;排序
使用ORDER BY子句可以对查询结果进行排序:
SELECT column_list
FROM table_name
ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...;示例:
-- 按姓名升序排列
SELECT * FROM students ORDER BY name ASC;
-- 按年龄降序排列
SELECT * FROM students ORDER BY age DESC;
-- 多列排序(先按专业升序,再按年龄降序)
SELECT * FROM students ORDER BY major ASC, age DESC;限制结果
使用LIMIT子句可以限制返回的记录数,常用于分页查询:
SELECT column_list
FROM table_name
LIMIT offset, count;
-- 或者
LIMIT count OFFSET offset;示例:
-- 只返回前5条记录
SELECT * FROM students LIMIT 5;
-- 分页查询(每页10条,第1页)
SELECT * FROM students LIMIT 0, 10;
-- 或者
SELECT * FROM students LIMIT 10 OFFSET 0;
-- 分页查询(每页10条,第2页)
SELECT * FROM students LIMIT 10, 10;
-- 或者
SELECT * FROM students LIMIT 10 OFFSET 10;去重
使用DISTINCT关键字可以去除查询结果中的重复记录:
SELECT DISTINCT column_list FROM table_name;示例:
-- 查询所有不同的专业
SELECT DISTINCT major FROM students;
-- 查询不同专业和年级的组合
SELECT DISTINCT major, grade FROM students;聚合函数与分组查询
聚合函数用于对一组值执行计算并返回单个值。
聚合函数
常用的聚合函数包括:
COUNT():计算行数SUM():计算总和AVG():计算平均值MAX():找出最大值MIN():找出最小值
示例:
-- 计算学生总数
SELECT COUNT(*) AS 学生总数 FROM students;
-- 计算所有成绩的总和
SELECT SUM(grade) AS 总分 FROM enrollments;
-- 计算平均成绩
SELECT AVG(grade) AS 平均成绩 FROM enrollments;
-- 找出最高分和最低分
SELECT MAX(grade) AS 最高分, MIN(grade) AS 最低分 FROM enrollments;
-- 计算有成绩记录的数量
SELECT COUNT(grade) AS 有成绩记录数 FROM enrollments;分组查询
使用GROUP BY子句可以将查询结果按指定列分组:
SELECT column_list, aggregate_function(column_name)
FROM table_name
WHERE condition
GROUP BY column_list;示例:
-- 按专业分组统计学生人数
SELECT major, COUNT(*) AS 人数
FROM students
GROUP BY major;
-- 按课程分组计算平均成绩
SELECT course_id, AVG(grade) AS 平均成绩
FROM enrollments
GROUP BY course_id;
-- 按年级分组统计各专业学生人数
SELECT grade, major, COUNT(*) AS 人数
FROM students
GROUP BY grade, major;过滤分组
使用HAVING子句可以对分组结果进行过滤:
SELECT column_list, aggregate_function(column_name)
FROM table_name
WHERE condition
GROUP BY column_list
HAVING condition;示例:
-- 查询学生人数超过10人的专业
SELECT major, COUNT(*) AS 人数
FROM students
GROUP BY major
HAVING COUNT(*) > 10;
-- 查询平均成绩超过80分的课程
SELECT course_id, AVG(grade) AS 平均成绩
FROM enrollments
GROUP BY course_id
HAVING AVG(grade) > 80;重要提示:
- WHERE子句在分组前过滤行
- HAVING子句在分组后过滤分组
- WHERE子句中不能使用聚合函数
- HAVING子句中可以使用聚合函数
多表查询
在实际应用中,数据通常存储在多个相关的表中,需要使用多表查询来获取完整的信息。
表连接类型
内连接(INNER JOIN)
内连接返回两个表中匹配的记录:
SELECT column_list
FROM table1
INNER JOIN table2 ON table1.column = table2.column;示例:
-- 查询学生姓名和他们的成绩
SELECT s.name, c.course_name, e.grade
FROM students s
INNER JOIN enrollments e ON s.id = e.student_id
INNER JOIN courses c ON e.course_id = c.id;左连接(LEFT JOIN)
左连接返回左表的所有记录和右表中匹配的记录:
SELECT column_list
FROM table1
LEFT JOIN table2 ON table1.column = table2.column;示例:
-- 查询所有学生及其成绩(包括没有成绩的学生)
SELECT s.name, c.course_name, e.grade
FROM students s
LEFT JOIN enrollments e ON s.id = e.student_id
LEFT JOIN courses c ON e.course_id = c.id;右连接(RIGHT JOIN)
右连接返回右表的所有记录和左表中匹配的记录:
SELECT column_list
FROM table1
RIGHT JOIN table2 ON table1.column = table2.column;示例:
-- 查询所有课程及选课学生(包括没有学生选的课程)
SELECT c.course_name, s.name, e.grade
FROM courses c
RIGHT JOIN enrollments e ON c.id = e.course_id
RIGHT JOIN students s ON e.student_id = s.id;全连接(FULL JOIN)
MySQL不直接支持FULL JOIN,但可以用UNION模拟:
SELECT column_list
FROM table1
LEFT JOIN table2 ON table1.column = table2.column
UNION
SELECT column_list
FROM table1
RIGHT JOIN table2 ON table1.column = table2.column;连接条件
使用ON子句指定表之间的关联字段:
-- 使用ON子句
SELECT s.name, c.course_name
FROM students s
INNER JOIN enrollments e ON s.id = e.student_id
INNER JOIN courses c ON e.course_id = c.id;
-- 使用USING子句(当关联字段同名时)
SELECT s.name, e.grade
FROM students s
INNER JOIN enrollments e USING(id);自连接
自连接是将同一张表视为两张表进行连接:
-- 查询员工及其上级(假设employees表中有manager_id字段)
SELECT e.name AS 员工姓名, m.name AS 上级姓名
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;实践项目
为了巩固所学知识,建议进行以下实践项目:
实现学生成绩管理系统的CRUD操作
- 创建数据库和表:
-- 创建学生成绩管理系统数据库
CREATE DATABASE student_grade_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE student_grade_system;
-- 创建学生表
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
student_id VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(50) NOT NULL,
gender ENUM('男', '女'),
birth_date DATE,
major VARCHAR(50),
enrollment_date DATE DEFAULT (CURRENT_DATE)
);
-- 创建课程表
CREATE TABLE courses (
id INT AUTO_INCREMENT PRIMARY KEY,
course_code VARCHAR(20) UNIQUE NOT NULL,
course_name VARCHAR(100) NOT NULL,
credits INT DEFAULT 3,
teacher VARCHAR(50)
);
-- 创建成绩表
CREATE TABLE grades (
id INT AUTO_INCREMENT PRIMARY KEY,
student_id INT,
course_id INT,
grade DECIMAL(5,2),
exam_date DATE DEFAULT (CURRENT_DATE),
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);- 实现CRUD操作:
-- 插入学生信息
INSERT INTO students (student_id, name, gender, birth_date, major)
VALUES
('2021001', '张三', '男', '2003-05-15', '计算机科学'),
('2021002', '李四', '女', '2002-08-20', '软件工程');
-- 插入课程信息
INSERT INTO courses (course_code, course_name, credits, teacher)
VALUES
('CS101', '计算机科学导论', 3, '王教授'),
('MATH101', '高等数学', 4, '李教授');
-- 插入成绩信息
INSERT INTO grades (student_id, course_id, grade)
VALUES
(1, 1, 85.5),
(1, 2, 92.0),
(2, 1, 78.0);
-- 查询所有学生信息
SELECT * FROM students;
-- 查询特定学生的成绩
SELECT s.name, c.course_name, g.grade
FROM students s
JOIN grades g ON s.id = g.student_id
JOIN courses c ON g.course_id = c.id
WHERE s.student_id = '2021001';
-- 更新学生成绩
UPDATE grades
SET grade = 88.0
WHERE student_id = 1 AND course_id = 1;
-- 删除学生成绩记录
DELETE FROM grades WHERE student_id = 2 AND course_id = 1;编写多表联合查询
-- 查询每个学生的平均成绩
SELECT s.name, AVG(g.grade) AS 平均成绩
FROM students s
LEFT JOIN grades g ON s.id = g.student_id
GROUP BY s.id, s.name;
-- 查询每门课程的最高分和最低分
SELECT c.course_name, MAX(g.grade) AS 最高分, MIN(g.grade) AS 最低分
FROM courses c
LEFT JOIN grades g ON c.id = g.course_id
GROUP BY c.id, c.course_name;
-- 查询成绩优秀的学生(平均分>85)
SELECT s.name, AVG(g.grade) AS 平均成绩
FROM students s
JOIN grades g ON s.id = g.student_id
GROUP BY s.id, s.name
HAVING AVG(g.grade) > 85;
-- 查询每门课程的选课人数和平均分
SELECT c.course_name, COUNT(g.student_id) AS 选课人数, AVG(g.grade) AS 平均分
FROM courses c
LEFT JOIN grades g ON c.id = g.course_id
GROUP BY c.id, c.course_name;统计分析数据
-- 统计各专业学生人数
SELECT major, COUNT(*) AS 人数
FROM students
GROUP BY major;
-- 统计各课程平均分
SELECT c.course_name, AVG(g.grade) AS 平均分
FROM courses c
JOIN grades g ON c.id = g.course_id
GROUP BY c.id, c.course_name
ORDER BY 平均分 DESC;
-- 查询不及格的学生和课程
SELECT s.name, c.course_name, g.grade
FROM students s
JOIN grades g ON s.id = g.student_id
JOIN courses c ON g.course_id = c.id
WHERE g.grade < 60;
-- 查询优秀率(成绩>=90)统计
SELECT c.course_name,
COUNT(*) AS 总人数,
SUM(CASE WHEN g.grade >= 90 THEN 1 ELSE 0 END) AS 优秀人数,
AVG(CASE WHEN g.grade >= 90 THEN 1.0 ELSE 0.0 END) AS 优秀率
FROM courses c
JOIN grades g ON c.id = g.course_id
GROUP BY c.id, c.course_name;通过以上实践项目,您将掌握MySQL核心操作的各个方面,包括数据的增删改查、多表查询以及数据分析等重要技能。