实验四 存储过程及函数

一、实验目的与要求:

1、掌握存储过程工作原理、定义及操作方法

2、掌握函数工作原理、定义及操作方法

3、掌握游标工作原理、定义及操作方法

二、实验内容:

1. 创建存储过程,用来自动统计给定订单号的订单总金额

CREATE PROCEDURE CalculateOrderTotal(IN order_num INT, OUT total_amount DECIMAL(10,2))
BEGIN
    SELECT SUM(quantity * item_price) INTO total_amount
    FROM orderitems
    WHERE o_num = order_num;
    
    IF total_amount IS NULL THEN
        SET total_amount = 0.00;
    END IF;
END 
-- 调用存储过程
CALL CalculateOrderTotal(50010, @total);

-- 查看结果
SELECT @total AS '订单50010总金额';

 

 

2.创建存储过程,自动搜索并添加客户及供货商帐号信息到新建的用户信息表。

 ①增加用户表信息user

CREATE TABLE user (
    id INT(11) AUTO_INCREMENT NOT NULL,
    u_id INT(11) NOT NULL,
    pwd BLOB NOT NULL,
    remark VARCHAR(255) NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (u_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

 

② 创建两个存储过程,分别把客户表的c_id和供货商表s_id的字段自动添加到用户信息表,补充pwd和remark字段。

要求:id字段自动增加,u_id 字段即客户或供货商的编号,pwd字段用AES_ENCRYPT函数加密,密码统一设置为用户编号u_id的值连接123456(如在当前表中u_id为10001,则其密码是10001123456),密钥是'hello'; remark字段内容是‘customer'或'supplier’

 添加客户表帐号:

CREATE PROCEDURE AddCustomersToUser()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE customer_id INT;
    DECLARE cur CURSOR FOR SELECT c_id FROM customers;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    OPEN cur;
    
    read_loop: LOOP
        FETCH cur INTO customer_id;
        IF done THEN
            LEAVE read_loop;
        END IF;
        
        INSERT INTO user (u_id, pwd, remark)
        VALUES (
            customer_id,
            AES_ENCRYPT(CONCAT(customer_id, '123456'), 'hello'),
            'customer'
        );
    END LOOP;
    
    CLOSE cur;
END

 添加供货商帐号

CREATE PROCEDURE AddSuppliersToUser()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE supplier_id INT;
    DECLARE cur CURSOR FOR SELECT s_id FROM suppliers;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    OPEN cur;
    
    read_loop: LOOP
        FETCH cur INTO supplier_id;
        IF done THEN
            LEAVE read_loop;
        END IF;
        
        INSERT INTO user (u_id, pwd, remark)
        VALUES (
            supplier_id,
            AES_ENCRYPT(CONCAT(supplier_id, '123456'), 'hello'),
            'supplier'
        );
    END LOOP;
    
    CLOSE cur;
END

 

3.创建存储过程或函数来批量修正订单详情表orderitems中的水果价格与水果表fruits中的价格一致。

提示:用游标

CREATE PROCEDURE UpdateOrderItemPrices()
BEGIN
    -- 声明变量
    DECLARE done INT DEFAULT FALSE;
    DECLARE fruit_id VARCHAR(10);
    DECLARE current_price DECIMAL(8,2);
    
    -- 声明游标,获取所有水果ID和价格
    DECLARE fruit_cursor CURSOR FOR 
        SELECT f_id, f_price FROM fruits;
    
    -- 声明异常处理
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    -- 打开游标
    OPEN fruit_cursor;
    
    -- 开始循环处理每一条水果记录
    read_loop: LOOP
        -- 获取当前水果的ID和价格
        FETCH fruit_cursor INTO fruit_id, current_price;
        
        -- 如果没有更多记录则退出循环
        IF done THEN
            LEAVE read_loop;
        END IF;
        
        -- 更新orderitems表中对应水果的价格
        UPDATE orderitems 
        SET item_price = current_price
        WHERE f_id = fruit_id;
        
    END LOOP;
    
    -- 关闭游标
    CLOSE fruit_cursor;
    
    -- 输出完成信息
    SELECT CONCAT('全部更新') AS Message;
END

CALL UpdateOrderItemPrices();

-- 查看更新后的订单详情
SELECT * FROM orderitems;

-- 对比水果表中的价格
SELECT f_id, f_price FROM fruits;

 

 

三、实验小

1.实验中遇到的问题及解决过程

问题1:游标遍历不完整

现象:最初编写的存储过程只更新了部分记录

排查:发现没有正确处理游标结束条件

解决:添加了DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;语句

问题2:价格更新错误

现象:部分水果价格更新为NULL值

排查:发现某些水果在orderitems表中不存在

解决:添加条件判断,只更新存在的记录

2.实验中产生的错误及原因分析

在循环中重复打开已打开的游标

游标管理不当,应在循环外打开和关闭

3.实验体会和收获。

掌握了存储过程的基本结构和创建方法

学会了游标的使用方法和注意事项

理解了MySQL中异常处理的机制

熟悉了DELIMITER在存储过程中的作用

实践体会:

游标操作需要严格遵循"声明-打开-获取-关闭"的流程

存储过程调试比普通SQL复杂,需要分段测试

事务处理在批量更新中非常重要

错误处理机制能显著提高存储过程的健壮性

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值