create database if not exists school_db
character set utf8mb4
collate utf8mb4_unicode_ci;
create table if not exists students
(
id int primary key auto_increment,
student_no varchar(20) not null unique,
name varchar(50) not null,
gender enum ('男', '女') default '男',
age int check (age >= 0 and age <= 100),
class_id int,
enrollment_date date,
created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp on update current_timestamp,
index idx_class_id (class_id),
index idx_name (name)
) engine = innodb
default charset = utf8mb4;
create table if not exists classes
(
class_id int primary key auto_increment,
class_name varchar(50) not null,
major varchar(100),
head_teacher varchar(50)
);
create table if not exists scores
(
score_id int primary key auto_increment,
student_id int not null,
course_name varchar(100) not null,
score decimal(5, 2) check (score >= 0 and score <= 100),
exam_date date,
foreign key (student_id) references students (id) on delete cascade,
index idx_student_id (student_id),
index idx_course (course_name)
);
insert into classes (class_name, major, head_teacher)
values ('计算机2023级1班', '计算机科学与技术', '张老师'),
('软件工程2023级1班', '软件工程', '李老师'),
('网络安全2023级2班', '网络安全', '王老师');
insert into students (student_no, name, gender, age, class_id, enrollment_date)
values ('2023001', '张三', '男', 20, 1, '2023-09-01'),
('2023002', '李四', '女', 19, 1, '2023-09-01'),
('2023003', '王五', '男', 21, 2, '2023-09-01'),
('2023004', '赵六', '女', 20, 3, '2023-09-01'),
('2023005', '钱七', '男', 22, 2, '2023-09-01');
insert into scores (student_id, course_name, score, exam_date)
values (1, '数据库原理', 85.5, '2024-01-15'),
(1, '数据结构', 90.0, '2024-01-16'),
(2, '数据库原理', 88.0, '2024-01-15'),
(3, '数据结构', 76.5, '2024-01-16'),
(4, '网络安全基础', 92.5, '2024-01-17'),
(5, '软件工程', 81.0, '2024-01-18');
select *
from students;
select student_no, name, gender, age
from students;
select *
from students
where age > 20;
select *
from students
where name like '张%';
select *
from students
order by age desc;
select class_id, count(*) as student_count
from students
group by class_id;
select s.name, s.student_no, c.class_name, c.major
from students s
join classes c on s.class_id = c.class_id;
select *
from scores
where score > (select avg(score) from scores);
select *
from students
limit 2 offset 2;
update students
set age = 21
where name = '张三';
delete
from students
where student_no = '2023005';
insert into students (student_no, name, gender, age, class_id, enrollment_date)
values ('2023006', '孙八', '男', 23, 1, '2023-09-01');
insert into scores (student_id, course_name, score, exam_date)
values (1, '操作系统', 87.0, '2024-01-19'),
(2, '数据结构', 91.5, '2024-01-16');
create view v_student_details as
select s.id,
s.student_no,
s.name,
s.gender,
s.age,
s.enrollment_date,
c.class_name,
c.major,
c.head_teacher
from students s
left join classes c on s.class_id = c.class_id;
create view v_student_scores as
select s.student_no,
s.name,
sc.course_name,
sc.score,
sc.exam_date,
c.class_name
from students s
join scores sc on s.id = sc.student_id
left join classes c on s.class_id = c.class_id;
create view v_class_avg_scores as
select c.class_id,
c.class_name,
c.major,
count(distinct s.id) as student_count,
count(sc.score_id) as score_count,
round(avg(sc.score), 2) as avg_score
from classes c
left join students s on c.class_id = s.class_id
left join scores sc on s.id = sc.student_id
group by c.class_id, c.class_name, c.major;
select *
from v_student_details;
select *
from v_student_details
where class_name = '计算机2023级1班';
select student_no,
name,
count(*) as course_count,
round(avg(score), 2) as avg_score
from v_student_scores
group by student_no, name
order by avg_score desc;
select *
from v_student_scores
where score >= 90;
select class_name,
major,
student_count,
avg_score
from v_class_avg_scores
where avg_score is not null
order by avg_score desc;
create view v_simple_students as
select id, student_no, name, age
from students;
update v_simple_students
set age = 22
where student_no = '2023001';
delimiter
create procedure sp_get_all_students()
begin
select * from students order by id;
end
delimiter ;
delimiter
create procedure sp_get_students_by_class(
in p_class_id int
)
begin
select * from students where class_id = p_class_id order by name;
end
delimiter ;
delimiter
create procedure sp_add_student(
in p_student_no varchar(20),
in p_name varchar(50),
in p_gender enum ('男', '女'),
in p_age int,
in p_class_id int,
in p_enrollment_date date,
out p_result varchar(100)
)
begin
declare v_count int;
select count(*) into v_count from students where student_no = p_student_no;
if v_count > 0 then
set p_result = '学号已存在,添加失败';
else
insert into students (student_no, name, gender, age, class_id, enrollment_date)
values (p_student_no, p_name, p_gender, p_age, p_class_id, p_enrollment_date);
set p_result = concat('添加成功,学生id为:', last_insert_id());
end if;
end
delimiter ;
delimiter
create procedure sp_update_student_age(
in p_student_id int,
in p_new_age int,
out p_result varchar(100)
)
begin
declare v_exists int;
select count(*) into v_exists from students where id = p_student_id;
if v_exists = 0 then
set p_result = '学生不存在,更新失败';
elseif p_new_age < 0 or p_new_age > 100 then
set p_result = '年龄必须在0-100之间';
else
update students set age = p_new_age where id = p_student_id;
if row_count() > 0 then
set p_result = '年龄更新成功';
else
set p_result = '年龄更新失败';
end if;
end if;
end
delimiter ;
delimiter
create procedure sp_get_student_full_info(
in p_student_id int
)
begin
select '学生基本信息' as info_type, s.* from students s where s.id = p_student_id;
select '学生成绩' as info_type, sc.* from scores sc where sc.student_id = p_student_id;
select '学生平均分' as info_type,
round(avg(score), 2) as avg_score,
count(*) as course_count
from scores
where student_id = p_student_id;
end
delimiter ;
delimiter
create procedure sp_batch_insert_students(
in p_count int,
out p_message varchar(100)
)
begin
declare i int default 1;
declare v_student_no varchar(20);
declare v_class_id int;
declare exit handler for sqlexception
begin
rollback;
set p_message = '插入过程中发生错误,已回滚';
end;
start transaction;
while i <= p_count
do
set v_student_no = concat('test2024', lpad(i, 3, '0'));
set v_class_id = floor(rand() * 3) + 1;
insert into students (student_no, name, gender, age, class_id, enrollment_date)
values (v_student_no,
concat('测试学生', i),
if(rand() > 0.5, '男', '女'),
floor(rand() * 10) + 18,
v_class_id,
date_add('2023-09-01', interval floor(rand() * 30) day));
set i = i + 1;
end while;
commit;
set p_message = concat('成功插入', p_count, '条测试数据');
end
delimiter ;
call sp_get_all_students();
call sp_get_students_by_class(1);
set @result = '';
call sp_add_student('2023008', '周九', '女', 21, 1, '2023-09-01', @result);
select @result as 操作结果;
call sp_update_student_age(1, 22, @result);
select @result as 更新结果;
call sp_get_student_full_info(1);
call sp_batch_insert_students(5, @result);
select @result as 批量插入结果;
show procedure status where db = 'school_db';
show create procedure sp_get_all_students;
show full tables where table_type like 'view';
show create view v_student_details;
create or replace view v_simple_students as
select id, student_no, name, age, gender
from students;
drop view if exists v_simple_students;
start transaction;
insert into students (student_no, name, gender, age, class_id, enrollment_date)
values ('2023009', '吴十', '女', 20, 1, '2023-09-01');
insert into scores (student_id, course_name, score, exam_date)
values (last_insert_id(), '数据库原理', 95.0, '2024-01-20');
commit;