当前位置: 首页 > news >正文

头歌实训之存储过程、函数与触发器

🌟 各位看官好,我是maomi_9526

🌍 种一棵树最好是十年前,其次是现在!

🚀 今天来学习C语言的相关知识。

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

目录

第1关:创建存储过程

第2关:创建函数-count_credit

第3关:存储过程中使用游标

第4关:创建触发器-计算总学分 

第5关:创建触发器-级联删除

总结:头歌第二关及第三关

问题分析:


第1关:创建存储过程

任务描述
本关任务:创建存储过程,实现对学生姓名进行模糊查询。

相关知识
为了完成本关任务,你需要掌握:
1.存储过程的定义;
2.存储过程的创建;
3.存储过程的执行。

存储过程的定义
 存储过程(Stored Procedure)是数据库中一组预编译的SQL语句集合,存储在数据库中,可以被应用程序调用。存储过程可以包含复杂的逻辑、变量、条件判断和循环等,能够实现一些复杂的业务逻辑,提高代码的复用性和执行效率。

存储过程的创建
创建存储过程格式:

DELIMITER //
CREATE PROCEDURE 过程名([参数列表])
BEGIN
    -- SQL语句
END //
DELIMITER ;

  • DELIMITER:MySQL 默认的语句分隔符是分号(;),但在存储过程中,分号可能会被用作语句的分隔符,因此需要使用 DELIMITER 关键字来改变分隔符,通常将其改为 // 或其他符号,以免与存储过程内部的分号冲突。
  • 存储过程名称:存储过程的名称,用于后续调用存储过程时标识该存储过程。
  • 参数列表:存储过程的参数,可以有输入参数(IN)、输出参数(OUT)和输入输出参数(INOUT)。参数的格式为 参数名 参数类型,例如 IN id INT 表示一个输入参数 id,类型为整数。
  • BEGIN...END:存储过程的主体部分,包含需要执行的 SQL 语句。

执行存储过程

  • 调用存储过程的语法如下:

CALL 存储过程名称(参数值);

  • 存储过程名称:要调用的存储过程的名称。
  • 参数值:调用存储过程时传递的参数值(实参),参数值的顺序和类型应与存储过程定义时的参数列表一致。

编程要求

根据提示,在右侧编辑器补充代码,创建存储过程pro_findname(IN word CHAR(1)) 对学生姓名进行模糊查找,输入任一汉字,输出姓名中含有该汉字的全部学生信息。

测试说明
平台会对你编写的代码进行测试,将调用你编写的存储过程:call pro_findname('明'),具体输出请参考右侧测试集。


开始你的任务吧,祝你成功!

 use teachingdb;/****请在此编写代码,操作完毕之后点击评测******/
DELIMITER $$/**********Begin**********/create procedure pro_findname(in word char(10))Beginselect * from student where sname like concat('%',word,'%');
End $$/**********End**********/
DELIMITER ;

第2关:创建函数-count_credit

任务描述
本关任务:创建和使用存储函数。

相关知识
为了完成本关任务,你需要掌握:

  • 创建存储函数;
  • 调用存储函数。

创建存储函数

  • 存储函数(Stored Function)是一种在数据库中存储的可调用的函数,类似于存储过程,但存储函数的主要目的是返回一个值,而存储过程主要用于执行一系列操作。存储函数可以被 SQL 语句直接调用,也可以在其他存储过程或存储函数中调用。
  • 创建存储函数格式

DELIMITER //
CREATE FUNCTION 函数名称 (参数列表)
RETURNS 返回值类型  READS SQL DATA
BEGIN
    -- 函数的 SQL 语句
    RETURN 返回值;
END//
DELIMITER ;


调用函数

  • SELECT 函数名称(参数值);
  • 在表达式中使用函数名称(参数值)。

编程要求
根据提示,在右侧编辑器补充代码,设计函数 count_credit(sno CHAR(6)),根据学号(sno)计算该学生的总学分,只有当成绩大于等于60分时才能获得该门课程的学分。

测试说明
平台会对你编写的代码进行测试:本题中该学生选“马蓉”,学号为“97001”)


 开始你的任务吧,祝你成功!

 use teachingdb;/****请在此编写代码,操作完毕之后点击评测******//**********Begin**********/delimiter ##create Function count_credit(v_sno char(6))returns int reads sql dataBegindeclare sums int ;select sum(credit) into sums from course natural join score where grade >=60 and v_sno=sno;return sums;end ##delimiter ;/**********End**********/

第3关:存储过程中使用游标

任务描述
本关任务:创建存储过程 ,在存储过程中定义游标计算总学分。

相关知识
为了完成本关任务,你需要掌握:
1.游标的定义;
2.游标的使用。

游标的定义
游标(Cursor)主要用于存储过程和函数中,用于逐行处理查询结果集。

  • 在存储过程或函数中,使用 DECLARE CURSOR 语句来创建游标。

DECLARE cursor_name CURSOR FOR select_statement;

游标的使用

  • 打开游标

OPEN cursor_name;

  • 获取数据

FETCH cursor_name INTO var_name1, var_name2, ...;

  • 关闭游标

CLOSE cursor_name;


举例:通过游标获取users表中的id,name,并输出结果。

DELIMITER //
CREATE PROCEDURE process_users()
BEGIN
   -- 声明变量
   DECLARE finished INTEGER DEFAULT 0;
   DECLARE user_id INT DEFAULT 0;
   DECLARE user_name VARCHAR(50) DEFAULT '';
   -- 声明游标
   DECLARE my_cursor CURSOR FOR SELECT id, name FROM users;
   -- 声明结束处理
   DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
   -- 打开游标
   OPEN my_cursor;
   -- 获取数据
   fetch_loop: LOOP
       FETCH my_cursor INTO user_id, user_name;
       IF finished = 1 THEN
           LEAVE fetch_loop;
       END IF;
       -- 处理每一行数据
       SELECT user_id, user_name;
   END LOOP;
   -- 关闭游标
   CLOSE my_cursor;
END //
DELIMITER ;

编程要求
根据提示,在右侧编辑器补充代码,创建存储过程 p_count_credit,在存储过程中创建游标stucur保存所有学生的学号,使用loop循环从游标中提取每个学生的学号,根据当前学号调用count_credit 函数计算学生的总学分,并更新学生表中的总学分值。

测试说明
平台会对你编写的代码进行测试,将调用你编写的存储过程p_count_credit,函数的count_credit的功能和第2关中的相同,具体输出请参考右侧测试集。


开始你的任务吧,祝你成功!

 use teachingdb;/****请在此编写代码,操作完毕之后点击评测******//**********Begin**********/drop procedure if exists p_count_credit;delimiter ##create procedure  p_count_credit()begindeclare v_sno varchar(20);declare v_credit int default 0;declare stucur cursor for select sno from student;declare exit handler for not found close stucur ;open stucur;while true dofetch stucur into v_sno;update student set totalcredit =count_credit(v_sno) where sno=v_sno;end while;close stucur;select *from student;end ##delimiter ;/**********End**********/

第4关:创建触发器-计算总学分 

任务描述
本关任务:创建触发器 sum_credit,实现对 student 表总学分的计算。

相关知识
为了完成本关任务,你需要掌握:
1.触发器的定义;
2.触发器的创建。

触发器的定义
触发器(Trigger)是一种特殊的存储过程,它在表上的数据发生变化(如INSERT、UPDATE 和 DELETE操作)时自动执行。触发器的主要作用是维护数据的完整性和一致性,或者在数据变化时执行一些自动化的操作。

  • 触发时机:触发器可以设置在数据操作之前(BEFORE)或之后(AFTER)执行。
  • 触发事件:可以是INSERT、UPDATE或DELETE操作。

创建触发器的语法:


CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON table_name
FOR EACH ROW
BEGIN
    -- 触发器要执行的SQL语句
END;

  • BEFORE 或 AFTER 指定触发器应在事件之前还是之后触发。
  • INSERT, UPDATE, 或 DELETE 指定触发器应该响应的事件类型。

触发器表

  • 在 MySQL 触发器中,NEW 和 OLD 是两个特殊的虚拟表(实际上它们是行数据的引用),用于访问触发事件中涉及的数据。这两个虚拟表的具体含义和用途取决于触发器所关联的操作类型(INSERT、UPDATE 或 DELETE)。
  • NEW 表
    • NEW 表表示即将插入到表中的新行数据,或者在更新操作中表示更新后的新值。
    • 可用场景: 在 BEFORE INSERT 和 AFTER INSERT 中,NEW 表示将要插入的新行。 在 BEFORE UPDATE 和 AFTER UPDATE 中,NEW 表示更新后的字段值。
    • 用法:可以通过 NEW.column_name 来访问或修改某一列的值。

示例
(1)创建一触发器 t_u_s,实现在更新学生表的学号时,同时更新 grade 表中的相关记录的 student 的 id 值。

CREATE TRIGGER t_u_s
AFTER UPDATE ON student
for EACH ROW
BEGIN
    UPDATE grade SET studentid = new.studentid WHERE studentid = old.studentid;
END

  • OLD 表
  • OLD 表表示被删除或更新的旧行数据。
  • 可用场景: 在 BEFORE DELETE 和 AFTER DELETE 中,OLD 表示将要被删除的行。 在 BEFORE UPDATE 和 AFTER UPDATE 中,OLD 表示更新前的字段值。
  • 用法:可以通过 OLD.column_name 来访问某一列的值,但不能对其进行修改(因为它是只读的)。

示例
(2)建一个触发器 t_d_s,当删除表 student 中某个学生的信息时,同时将 grade 表中与该学生有关的数据全部删除。

CREATE TRIGGER trigger_t1
AFTER DELETE ON student
FOR EACH ROW
BEGIN 
    DELETE FROM grade WHERE studentid = old.studentid;
END

编程要求
根据提示,在右侧编辑器补充代码,创建触发器 sum_credit,实现对 student 表总学分的计算,当 score 中添加一条记录时,student 表总学分的值做相应改变。当课程成绩大于等于60分时,将该课程的学分加到该学生的总学分中。

测试说明
平台会对你编写的代码进行测试:平台会用“马小燕”为测试用例进行测试。


开始你的任务吧,祝你成功!

 use teachingdb;/****请在此编写代码,操作完毕之后点击评测******//**********Begin**********/delimiter ##create trigger sum_creditafter insert on score for each rowBeginif(new.grade>=60) thenupdate student set totalcredit =totalcredit+(select credit from course where cno=new.cno)where student.sno=new.sno;end if;end ##delimiter ;/**********End**********/

第5关:创建触发器-级联删除

任务描述
本关任务:创建级联删除触发器 。

相关知识
为了完成本关任务,你需要掌握:
1.级联删除的定义;
2.级联删除的工作原理。

级联删除的定义

  • 级联删除(Cascade Delete)是数据库管理系统中的一种功能,用于定义外键约束时指定的删除规则。当一个表中的记录被删除时,所有关联的记录也会根据级联删除规则自动删除。这确保了数据的一致性,避免出现孤立记录(即那些指向已删除记录的外键值)。

级联删除的工作原理

  • 级联删除的工作原理
    • 假设你有两个表:Parent 和 Child。Child 表通过外键关联到 Parent 表。当你在 Parent 表上设置级联删除时,如果从 Parent 表中删除一条记录,那么所有在 Child 表中与这条记录相关联的记录也将被自动删除。

编程要求
根据提示,在右侧编辑器补充代码,创建级联删除触发器 del_student_score,当删除 student 表中的某学生时,也删除 score 表中的对应学号的学生选课记录。

测试说明
平台会对你编写的代码进行测试。


开始你的任务吧,祝你成功!

 use teachingdb;/****请在此编写代码,操作完毕之后点击评测******//**********Begin**********/delimiter ##create trigger del_studnet_scorebefore delete on student for each rowbegindelete from score where sno=old.sno;end ##delimiter ;/**********End**********/

总结:头歌第二关及第三关

常见答题系统工作原理: 

问题分析:

在头歌平台的测试过程中,由于他们只进行公开测试用例的验证,部分潜在的逻辑错误可能没有被及时发现。这种情况尤其会影响到 MySQL 相关的习题,因为这些习题通常会涉及到数据库操作的细节,如果没有合适的隐藏测试用例,某些问题可能不会暴露。

例如实验五第二关:

自己代码:官方代码:
 use teachingdb;
 /****请在此编写代码,操作完毕之后点击评测******/
 
 /**********Begin**********/
  delimiter ##
  create Function count_credit(v_sno char(6))
  returns float reads sql data
  Begin
  declare sums float;
  select sum(credit) into sums from course natural join score where grade >=60 and v_sno=sno;
    return sums;
  end ##
  delimiter ;
  
 /**********End**********/
CREATE DEFINER=`root`@`localhost` FUNCTION `count_credit`(stuno CHAR(6)) 
RETURNS int(11)
    READS SQL DATA
BEGIN
    DECLARE stucno CHAR(3);  
    DECLARE cred INT DEFAULT 0;
    DECLARE t_cred INT DEFAULT 0;
    DECLARE done INT DEFAULT FALSE;
    
    -- 定义游标,从score表中获取学生所选课程编号
    DECLARE stucur CURSOR FOR 
        SELECT cno 
        FROM score 
        WHERE sno = stuno AND grade >= 60;
    
    -- 定义处理游标未找到数据时的行为
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    -- 打开游标
    OPEN stucur;
    
    -- 循环获取课程编号并累加学分
    loop_cursor: LOOP
        FETCH stucur INTO stucno;
        IF done THEN 
            LEAVE loop_cursor;
        END IF;
        
        -- 获取课程学分
        SELECT credit INTO cred 
        FROM course 
        WHERE cno = stucno;
        
        -- 累加学分
        SET t_cred = t_cred + cred;
    END LOOP;
    
    -- 返回总学分
    RETURN t_cred;
END
 

 勘误:因为官方只进行公开实例进行测试,这里都可以进行通过

 

Mysql习题一般都是继续使用官方的代码进行测试,如果你在第三关依旧写出float的代码 */

 use teachingdb;/****请在此编写代码,操作完毕之后点击评测******//**********Begin**********/
select sum(credit) from score natural join course  where sno='96002';drop procedure if exists p_count_credit;delimiter ##create procedure  p_count_credit()begindeclare v_sno varchar(20);declare v_credit float default 0;declare stucur cursor for select sno from student;declare exit handler for not found close stucur ;open stucur;while true dofetch stucur into v_sno;select sum(credit) into v_credit from score natural join course where grade>=60 and sno=v_sno;update student set totalcredit =ifnull(v_credit,0) where sno=v_sno;end while;close stucur;select *from student;end ##delimiter ;/**********End**********/

由于头歌平台的测试机制仅依赖于公开的测试用例,这导致了部分潜在的逻辑问题没有被及时发现。尽管我们无法修改平台的测试方式或其隐藏的测试用例,但我们可以选择按照平台提供的标准函数进行测试,以确保代码在实际评测时能够正确运行。

本次纠错并没有涉及复杂的新知识点,而是希望同学们能够理解,为什么在这种情况下,某些潜在的错误未被立即发现,当大家出现这种情况也可以通过下面这种方法来通过测试:

相关文章:

  • 【数据结构入门训练DAY-24】美国大选
  • MCP 安全困境与Agent安全框架的应对之道
  • 深度理解linux系统—— 了解操作系统
  • Maven的概念与初识Maven
  • Android JIT( ART即时编译器),Just In Time Compiler,即时编译技术
  • 【大模型】Coze AI 智能体工作流从配置到使用实战详解
  • Simulink 数据存储机制:Base Workspace、Model Workspace 与 Data Dictionary 的核心区别
  • Python + Playwright:如何在Docker 容器运行测试?
  • docker容器运维工具——ctop
  • 基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
  • node入门和npm
  • 当自动驾驶遇上“安全驾校”:NVIDIA如何用技术给无人驾驶赋能?
  • java智慧城管综合管理系统源码,前端框架:vue+element;后端框架:springboot;移动端:uniapp开发,技术前沿,可扩展性强
  • 图像处理——边缘检测
  • RASP技术在DevOps中的安全应用
  • 冯·诺依曼和哈佛架构​​​​两种架构的总线组成及核心特点
  • Flink反压问题解析
  • 1--Python基础课程实验指导书
  • linux blueZ 第四篇:BLE GATT 编程与自动化——Python 与 C/C++ 实战
  • CSS3布局方式介绍
  • 因高颜值走红的女通缉犯出狱后当主播自称“改邪归正”,账号已被封
  • 关键词看中国经济“一季报”:稳,开局良好看信心
  • 单位被裁定补缴12年社保,滞纳金该谁出?
  • 咖啡与乳腺健康之间,究竟有着怎样的复杂关系?
  • 2025年全国贸易摩擦应对工作会议在京召开
  • 农贸美学、业态再构、智能管理,今天的菜市场不止有菜