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从基础到高级的所有操作,真正实现从入门到起飞的目标!

相关推荐
或与且与或非3 小时前
rust使用sqlx示例
开发语言·数据库·rust
知识分享小能手3 小时前
React学习教程,从入门到精通,React Router 语法知识点及使用方法详解(28)
前端·javascript·学习·react.js·前端框架·vue·react
王不忘.3 小时前
MySQL 数据库核心知识点详解
数据库·mysql
时序数据说4 小时前
时序数据库 IoTDB:支撑万亿级物联网设备的基石
大数据·数据库·物联网·时序数据库·iotdb
橙-极纪元4 小时前
11种数据库类型详解-第3种:时序数据库(TSDB)
数据库·时序数据库
摆个烂4 小时前
时序数据库深度解析:从基础概念到未来趋势
数据库·时序数据库
潲爺4 小时前
Java IDEA学习之路:第二周课程笔记归纳
java·笔记·学习
时序数据说4 小时前
哪些行业需要使用时序数据库?
大数据·数据库·物联网·时序数据库
开着拖拉机回家4 小时前
【MongoDB】mongoDB数据迁移
数据库·mongodb·nosql·数据库迁移·mongodump·mongorestore