SQL从入门到起飞:完整数据库操作练习

可以先看上篇文章,包含对数据库创建、表创建、表数据插入。SQL查询从入门到起飞。
SQL从入门到起飞:完整学习数据库与100+练习题

下面我将补充数据库操作(DDL、DML)的练习题目,包括创建数据库、表、插入、更新、删除等操作。

DDL(数据定义语言)练习

数据库操作

  1. 创建一个名为university_db的数据库
  2. 查看所有数据库列表
  3. 切换到university_db数据库
  4. 删除university_db数据库(练习后恢复)

表操作

  1. 创建一个faculty表,包含字段:faculty_id(主键), faculty_name, dean_name, established_year
  2. 修改students表,添加一个phone_number字段
  3. 修改students表,将scholarship字段改为DECIMAL(10,2)
  4. teachers表添加一个索引在department_id字段上
  5. 创建一个course_prerequisites表来管理课程先修关系
  6. library表添加一个唯一约束在isbn字段上
  7. 创建一个视图student_course_grades,显示学生姓名、课程名称和成绩
  8. 创建一个存储过程get_student_info,根据学生ID返回学生信息
  9. 创建一个触发器,在删除学生前检查是否有相关记录
  10. scores表添加检查约束,确保成绩在0-100之间
  11. 创建一个临时表存储成绩优秀的学生信息

DML(数据操作语言)练习

插入操作

  1. faculty表插入3个学院的数据
  2. students表插入5名新学生的数据
  3. teachers表插入3名新教师的数据
  4. courses表插入2门新课程的数据
  5. enrollments表插入10条选课记录
  6. scores表插入相应的成绩记录
  7. 使用INSERT...SELECT语句将计算机系学生复制到一个新表
  8. 批量插入多条图书馆藏书记录
  9. 插入一条借阅记录,包括借书和预计归还日期
  10. 使用多行插入语法一次性插入多个社团信息

更新操作

  1. 将所有教师的工资增加10%
  2. 将计算机系学生的奖学金增加1000元
  3. 将"数据库系统"课程的成绩全部提高5分(不超过100分)
  4. 更新所有逾期未还书的罚款金额(每天0.5元)
  5. 将2022年入学学生的院系改为新成立的"人工智能"系
  6. 将所有教授的职称更新为"正教授"
  7. 将没有投影仪的教室添加投影仪设备
  8. 将选修了"Java程序设计"且成绩低于60分的学生成绩改为60分
  9. 将所有社团的预算增加20%
  10. 将年龄大于20岁的学生的奖学金减少500元

删除操作

  1. 删除所有成绩为0的记录
  2. 删除没有学生选修的课程
  3. 删除借阅记录中已归还且无罚款的记录
  4. 删除没有成员参加的社团
  5. 删除2023年之前的所有活动记录
  6. 使用事务删除一个学生及其所有相关记录
  7. 删除重复的选课记录(同一学生同一课程多次选课)
  8. 删除没有安排教室的课程安排记录
  9. 删除可用副本数为0的图书记录
  10. 删除工资低于平均工资的教师记录

综合操作练习

  1. 创建一个新表alumni,并将已毕业学生的数据转移至此表
  2. 使用MERGE语句同步学生表和校友表的数据
  3. 使用CASE语句更新学生奖学金等级(90分以上A等,80-89分B等,其他C等)
  4. 使用事务处理借书操作(减少可用副本数,添加借阅记录)
  5. 使用游标遍历所有学生并更新其年龄字段
  6. 创建一个函数计算学生的GPA(平均学分绩点)
  7. 创建一个存储过程用于分页查询学生信息
  8. 使用临时表统计每个院系的学生成绩分布
  9. 使用公用表表达式(CTE)查询学生的选课路径
  10. 使用窗口函数计算每个学生的成绩排名

完整示例代码

DDL操作示例

sql 复制代码
-- 1. 创建数据库
CREATE DATABASE IF NOT EXISTS university_db;
USE university_db;

-- 5. 创建院系表
CREATE TABLE faculty (
    faculty_id INT PRIMARY KEY AUTO_INCREMENT,
    faculty_name VARCHAR(100) NOT NULL,
    dean_name VARCHAR(100),
    established_year INT
);

-- 6. 修改学生表添加电话号码字段
ALTER TABLE students ADD COLUMN phone_number VARCHAR(15);

-- 7. 修改学生表奖学金字段类型
ALTER TABLE students MODIFY COLUMN scholarship DECIMAL(10,2);

-- 9. 创建课程先修关系表
CREATE TABLE course_prerequisites (
    prerequisite_id INT PRIMARY KEY AUTO_INCREMENT,
    course_id INT NOT NULL,
    required_course_id INT NOT NULL,
    minimum_grade DECIMAL(5,2) DEFAULT 60.00,
    FOREIGN KEY (course_id) REFERENCES courses(course_id),
    FOREIGN KEY (required_course_id) REFERENCES courses(course_id)
);

-- 10. 为图书馆表添加ISBN唯一约束
ALTER TABLE library ADD CONSTRAINT uc_isbn UNIQUE (isbn);

-- 11. 创建学生成绩视图
CREATE VIEW student_course_grades AS
SELECT 
    s.student_id,
    s.first_name,
    s.last_name,
    c.course_name,
    sc.midterm_score,
    sc.final_score,
    sc.total_score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id
JOIN scores sc ON e.enrollment_id = sc.enrollment_id;

-- 12. 创建获取学生信息的存储过程
DELIMITER //
CREATE PROCEDURE get_student_info(IN student_id INT)
BEGIN
    SELECT 
        s.student_id,
        s.first_name,
        s.last_name,
        s.email,
        s.enrollment_date,
        d.department_name,
        s.scholarship
    FROM students s
    JOIN departments d ON s.department_id = d.department_id
    WHERE s.student_id = student_id;
END //
DELIMITER ;

-- 13. 创建删除学生前的检查触发器
DELIMITER //
CREATE TRIGGER before_student_delete
BEFORE DELETE ON students
FOR EACH ROW
BEGIN
    DECLARE enrollment_count INT;
    DECLARE borrow_count INT;
    
    -- 检查是否有选课记录
    SELECT COUNT(*) INTO enrollment_count 
    FROM enrollments 
    WHERE student_id = OLD.student_id;
    
    -- 检查是否有借阅记录
    SELECT COUNT(*) INTO borrow_count 
    FROM borrow_records 
    WHERE student_id = OLD.student_id AND return_date IS NULL;
    
    IF enrollment_count > 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Cannot delete student with course enrollments';
    END IF;
    
    IF borrow_count > 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Cannot delete student with borrowed books';
    END IF;
END //
DELIMITER ;

-- 14. 添加成绩检查约束
ALTER TABLE scores 
ADD CONSTRAINT chk_score_range 
CHECK (
    (midterm_score BETWEEN 0 AND 100 OR midterm_score IS NULL) AND
    (final_score BETWEEN 0 AND 100 OR final_score IS NULL) AND
    (assignment_score BETWEEN 0 AND 100 OR assignment_score IS NULL)
);

-- 15. 创建临时表存储优秀学生
CREATE TEMPORARY TABLE top_students AS
SELECT 
    s.student_id,
    s.first_name,
    s.last_name,
    AVG(sc.total_score) AS average_score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN scores sc ON e.enrollment_id = sc.enrollment_id
GROUP BY s.student_id, s.first_name, s.last_name
HAVING AVG(sc.total_score) >= 90;

DML操作示例

sql 复制代码
-- 16. 插入学院数据
INSERT INTO faculty (faculty_name, dean_name, established_year) VALUES
('工程学院', '张院长', 2000),
('理学院', '李院长', 1995),
('文学院', '王院长', 1985);

-- 17. 插入新学生数据
INSERT INTO students (first_name, last_name, email, enrollment_date, date_of_birth, department_id, scholarship, phone_number) VALUES
('唐', '雨', 'tangyu@email.com', '2023-09-01', '2004-12-03', 1, 2000.00, '13800138000'),
('宋', '阳', 'songyang@email.com', '2023-09-01', '2004-07-21', 2, 1500.00, '13900139000'),
('秦', '雪', 'qinxue@email.com', '2023-09-01', '2004-03-15', 3, 0.00, '13700137000'),
('许', '明', 'xuming@email.com', '2023-09-01', '2004-09-28', 4, 1000.00, '13600136000'),
('何', '静', 'hejing@email.com', '2023-09-01', '2004-11-11', 5, 2500.00, '13500135000');

-- 18. 插入新教师数据
INSERT INTO teachers (first_name, last_name, email, hire_date, department_id, title, salary) VALUES
('韩', '教授', 'han@email.com', '2021-06-10', 1, '副教授', 72000.00),
('董', '老师', 'dong@email.com', '2022-02-15', 2, '讲师', 58000.00),
('曹', '教授', 'cao@email.com', '2019-08-20', 3, '教授', 88000.00);

-- 19. 插入新课程数据
INSERT INTO courses (course_code, course_name, credits, teacher_id, department_id) VALUES
('CS501', '人工智能', 4, 1, 1),
('MATH401', '数值分析', 3, 10, 2);

-- 20. 插入选课记录
INSERT INTO enrollments (student_id, course_id, enrollment_date, semester, academic_year) VALUES
(16, 14, '2023-09-05', 'Fall', 2023),
(17, 15, '2023-09-05', 'Fall', 2023),
(18, 14, '2023-09-06', 'Fall', 2023),
(19, 15, '2023-09-06', 'Fall', 2023),
(20, 14, '2023-09-07', 'Fall', 2023),
(16, 1, '2023-09-07', 'Fall', 2023),
(17, 5, '2023-09-08', 'Fall', 2023),
(18, 8, '2023-09-08', 'Fall', 2023),
(19, 10, '2023-09-09', 'Fall', 2023),
(20, 11, '2023-09-09', 'Fall', 2023);

-- 26. 更新教师工资增加10%
UPDATE teachers SET salary = salary * 1.1;

-- 27. 更新计算机系学生奖学金
UPDATE students s
JOIN departments d ON s.department_id = d.department_id
SET s.scholarship = s.scholarship + 1000
WHERE d.department_name = '计算机科学';

-- 28. 更新数据库系统课程成绩
UPDATE scores sc
JOIN enrollments e ON sc.enrollment_id = e.enrollment_id
JOIN courses c ON e.course_id = c.course_id
SET sc.final_score = LEAST(sc.final_score + 5, 100)
WHERE c.course_name = '数据库系统';

-- 29. 更新逾期罚款
UPDATE borrow_records 
SET fine_amount = DATEDIFF(CURDATE(), due_date) * 0.5
WHERE return_date IS NULL AND due_date < CURDATE();

-- 36. 删除成绩为0的记录
DELETE FROM scores WHERE total_score = 0;

-- 37. 删除没有学生选修的课程
DELETE FROM courses 
WHERE course_id NOT IN (SELECT DISTINCT course_id FROM enrollments);

-- 41. 使用事务删除学生及相关记录
START TRANSACTION;

-- 首先删除相关记录
DELETE FROM scores WHERE enrollment_id IN (
    SELECT enrollment_id FROM enrollments WHERE student_id = 15
);
DELETE FROM enrollments WHERE student_id = 15;
DELETE FROM borrow_records WHERE student_id = 15;
DELETE FROM club_members WHERE student_id = 15;
DELETE FROM event_participants WHERE student_id = 15;

-- 最后删除学生
DELETE FROM students WHERE student_id = 15;

COMMIT;

综合操作示例

sql 复制代码
-- 46. 创建校友表并转移数据
CREATE TABLE alumni (
    alumni_id INT PRIMARY KEY AUTO_INCREMENT,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    enrollment_date DATE,
    graduation_date DATE,
    department_id INT,
    current_job VARCHAR(100),
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

-- 转移已毕业学生数据(假设2022年入学学生已毕业)
INSERT INTO alumni (first_name, last_name, email, enrollment_date, graduation_date, department_id)
SELECT first_name, last_name, email, enrollment_date, '2023-06-30', department_id
FROM students
WHERE enrollment_date < '2023-01-01';

-- 47. 使用MERGE语句同步数据(MySQL不支持MERGE,使用INSERT...ON DUPLICATE KEY UPDATE)
INSERT INTO alumni (first_name, last_name, email, enrollment_date, graduation_date, department_id)
SELECT first_name, last_name, email, enrollment_date, '2023-06-30', department_id
FROM students
WHERE enrollment_date < '2023-01-01'
ON DUPLICATE KEY UPDATE 
    first_name = VALUES(first_name),
    last_name = VALUES(last_name),
    graduation_date = VALUES(graduation_date),
    department_id = VALUES(department_id);

-- 48. 使用CASE更新奖学金等级
UPDATE students s
JOIN (
    SELECT 
        s.student_id,
        CASE 
            WHEN AVG(sc.total_score) >= 90 THEN 'A'
            WHEN AVG(sc.total_score) >= 80 THEN 'B'
            ELSE 'C'
        END AS scholarship_grade
    FROM students s
    JOIN enrollments e ON s.student_id = e.student_id
    JOIN scores sc ON e.enrollment_id = sc.enrollment_id
    GROUP BY s.student_id
) grades ON s.student_id = grades.student_id
SET s.scholarship = 
    CASE grades.scholarship_grade
        WHEN 'A' THEN 5000
        WHEN 'B' THEN 3000
        ELSE 1000
    END;

-- 49. 使用事务处理借书操作
START TRANSACTION;

-- 检查书籍是否可用
SELECT available_copies INTO @available FROM library WHERE book_id = 5;

IF @available > 0 THEN
    -- 减少可用副本数
    UPDATE library SET available_copies = available_copies - 1 WHERE book_id = 5;
    
    -- 添加借阅记录
    INSERT INTO borrow_records (student_id, book_id, borrow_date, due_date)
    VALUES (1, 5, CURDATE(), DATE_ADD(CURDATE(), INTERVAL 30 DAY));
    
    COMMIT;
ELSE
    ROLLBACK;
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Book not available';
END IF;

-- 51. 创建计算GPA的函数
DELIMITER //
CREATE FUNCTION calculate_gpa(student_id INT) RETURNS DECIMAL(3,2)
READS SQL DATA
BEGIN
    DECLARE total_points DECIMAL(5,2);
    DECLARE total_credits INT;
    DECLARE gpa DECIMAL(3,2);
    
    SELECT 
        SUM(CASE 
            WHEN sc.total_score >= 90 THEN 4.0 * c.credits
            WHEN sc.total_score >= 80 THEN 3.0 * c.credits
            WHEN sc.total_score >= 70 THEN 2.0 * c.credits
            WHEN sc.total_score >= 60 THEN 1.0 * c.credits
            ELSE 0
        END),
        SUM(c.credits)
    INTO total_points, total_credits
    FROM students s
    JOIN enrollments e ON s.student_id = e.student_id
    JOIN courses c ON e.course_id = c.course_id
    JOIN scores sc ON e.enrollment_id = sc.enrollment_id
    WHERE s.student_id = student_id;
    
    IF total_credits > 0 THEN
        SET gpa = total_points / total_credits;
    ELSE
        SET gpa = 0;
    END IF;
    
    RETURN gpa;
END //
DELIMITER ;

-- 52. 创建分页查询存储过程
DELIMITER //
CREATE PROCEDURE get_students_paginated(
    IN page_number INT,
    IN page_size INT,
    OUT total_students INT,
    OUT total_pages INT
)
BEGIN
    -- 获取总学生数
    SELECT COUNT(*) INTO total_students FROM students;
    
    -- 计算总页数
    SET total_pages = CEIL(total_students / page_size);
    
    -- 分页查询学生
    SELECT *
    FROM students
    ORDER BY student_id
    LIMIT page_size
    OFFSET (page_number - 1) * page_size;
END //
DELIMITER ;

-- 53. 使用临时表统计成绩分布
CREATE TEMPORARY TABLE grade_distribution AS
SELECT 
    d.department_name,
    COUNT(*) AS total_students,
    SUM(CASE WHEN gpa >= 3.5 THEN 1 ELSE 0 END) AS excellent,
    SUM(CASE WHEN gpa >= 2.5 AND gpa < 3.5 THEN 1 ELSE 0 END) AS good,
    SUM(CASE WHEN gpa >= 1.5 AND gpa < 2.5 THEN 1 ELSE 0 END) AS average,
    SUM(CASE WHEN gpa < 1.5 THEN 1 ELSE 0 END) AS poor
FROM (
    SELECT 
        s.student_id,
        s.department_id,
        calculate_gpa(s.student_id) AS gpa
    FROM students s
) student_gpas
JOIN departments d ON student_gpas.department_id = d.department_id
GROUP BY d.department_name;

-- 54. 使用CTE查询选课路径
WITH RECURSIVE course_path AS (
    -- 基础查询:没有先修课程的课程
    SELECT 
        course_id,
        course_name,
        CAST(course_name AS CHAR(500)) AS path
    FROM courses
    WHERE prerequisite_id IS NULL
    
    UNION ALL
    
    -- 递归查询:有先修课程的课程
    SELECT 
        c.course_id,
        c.course_name,
        CONCAT(cp.path, ' -> ', c.course_name)
    FROM courses c
    JOIN course_path cp ON c.prerequisite_id = cp.course_id
)
SELECT * FROM course_path;

-- 55. 使用窗口函数计算成绩排名
SELECT 
    s.student_id,
    s.first_name,
    s.last_name,
    c.course_name,
    sc.total_score,
    RANK() OVER (PARTITION BY c.course_id ORDER BY sc.total_score DESC) AS course_rank,
    RANK() OVER (PARTITION BY s.department_id ORDER BY sc.total_score DESC) AS department_rank
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id
JOIN scores sc ON e.enrollment_id = sc.enrollment_id;

学习建议

  1. 先掌握基本的DDL语句(CREATE, ALTER, DROP)
  2. 熟练使用DML语句(INSERT, UPDATE, DELETE)
  3. 学习事务处理(BEGIN, COMMIT, ROLLBACK)
  4. 掌握约束的使用(主键、外键、唯一、检查约束)
  5. 学习视图、存储过程、函数和触发器的创建与使用
  6. 练习复杂的数据操作和业务逻辑实现
  7. 学习性能优化技巧(索引、查询优化)
  8. 定期备份和恢复数据库

通过这些完整的数据库操作练习,你将全面掌握SQL从基础到高级的所有操作,真正实现从入门到起飞的目标!

相关推荐
小蒜学长26 分钟前
springboot餐厅信息管理系统设计(代码+数据库+LW)
java·数据库·spring boot·后端
Justin_1930 分钟前
mysql数据库高级特性(一)
数据库·mysql
试试勇气36 分钟前
Linux学习笔记(八)--环境变量与进程地址空间
linux·笔记·学习
蒙奇D索大38 分钟前
【数据结构】考研数据结构核心考点:平衡二叉树(AVL树)详解——平衡因子与4大旋转操作入门指南
数据结构·笔记·学习·考研·改行学it
邂逅you1 小时前
用python操作mysql之pymysql库基本操作
数据库·python·mysql
心 一1 小时前
接口安全测试实战:从数据库错误泄露看如何构建安全防线
数据库·安全
点灯小铭1 小时前
基于单片机的PID调节脉动真空灭菌器上位机远程监控设计
数据库·单片机·嵌入式硬件·毕业设计·课程设计
andwhataboutit?1 小时前
Docker Compose学习
学习·docker·容器
小高Baby@1 小时前
Redis Key的设计
数据库·redis·缓存
im_AMBER2 小时前
数据结构 04 栈和队列
数据结构·笔记·学习