【问题标题】:How to properly write a cursor inside a function?如何在函数内正确编写游标?
【发布时间】:2020-02-09 08:29:44
【问题描述】:

我需要你的帮助,因为我有点迷路了。我试图在谷歌上查看函数中的游标和关于这些的引用,但我似乎无法完全理解这个概念。我有一个需要做的作业:

  • 创建一个我在其中使用游标的函数
  • 录入为加薪百分比(例:5%为0.05)
  • 函数需要用新的涨价来更新工资
  • 显示新的平均工资
  • 并处理可能的错误

这是我到目前为止所做的......

您能帮我解决提示问题,或者至少是函数中游标的简单示例/资源,以便我可以开始更好地掌握这个概念。

DROP FUNCTION IF EXISTS Program;
DELIMITER //
CREATE FUNCTION Program(IncSal DECIMAL(3,2))
RETURNS DECIMAL(8,2)
DETERMINISTIC
    BEGIN
        DECLARE Salaire DECIMAL (8,2);
        DECLARE end BOOLEAN DEFAULT FALSE;
        DECLARE CurSalary CURSOR FOR
            SELECT Sala_EMPL
                        FROM EMPLOYE;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET end = TRUE;      

        OPEN CurSalary;
            loop_cursor: LOOP
                IF end THEN 
                    LEAVE loop_cursor; 
                END IF;
                UPDATE EMPLOYE
                SET Sala_EMPL=(Sala_EMPL*IncSal);
            END LOOP;
        CLOSE CurSalary;

        RETURN AVG(CurSalary);
    END; 
    //
    DELIMITER ;

【问题讨论】:

    标签: mysql function cursors


    【解决方案1】:

    如果您使用游标,则必须从游标中获取(请查看https://dev.mysql.com/doc/refman/8.0/en/fetch.html)而不进行获取,循环是无限的。 AVG 是一个聚合函数,你不能在光标上进行 AVG(你需要一个 select..from)。每次迭代游标循环时,您的更新语句都将应用于所有员工(逻辑上很荒谬)。就我个人而言,我永远不会使用函数,因为您尝试做的事情在函数中并不合适(我会使用过程)。

    “工作”但功能错误的示例

    DROP FUNCTION IF EXISTS f;
    DELIMITER //
    CREATE FUNCTION f(IncSal DECIMAL(3,2))
    RETURNS DECIMAL(8,2)
    DETERMINISTIC
        BEGIN
            DECLARE Salaire DECIMAL (8,2);
            DECLARE end BOOLEAN DEFAULT FALSE;
            DECLARE CurSalary CURSOR FOR
            SELECT salary FROM EMPLOYEe;
            DECLARE CONTINUE HANDLER FOR NOT FOUND SET end = TRUE;      
    
            OPEN CurSalary;
                loop_cursor: LOOP
                     fetch cursalary into salaire;
                    IF end THEN 
                        LEAVE loop_cursor; 
                    END IF;
                    UPDATE EMPLOYEe
                                SET Salary=salary + (salary*incsal);
                END LOOP;
            CLOSE CurSalary;
    
            #RETURN AVG(CurSalary);
            return (select avg(salary) from employee);
        END; 
        //
        DELIMITER ;
    
    MariaDB [sandbox]> select * from employee;
    +------------+-----------+--------------+--------+
    | employeeid | firstname | departmentid | salary |
    +------------+-----------+--------------+--------+
    |          1 | aaa       |            1 |  10000 |
    |          2 | bbb       |            2 |  10000 |
    |          3 | ccc       |            3 |  10000 |
    +------------+-----------+--------------+--------+
    3 rows in set (0.00 sec)
    
    MariaDB [sandbox]>
    MariaDB [sandbox]>     select f(.05);
    +----------+
    | f(.05)   |
    +----------+
    | 11576.00 |
    +----------+
    1 row in set (0.00 sec)
    
    MariaDB [sandbox]>
    MariaDB [sandbox]>     select * from employee;
    +------------+-----------+--------------+--------+
    | employeeid | firstname | departmentid | salary |
    +------------+-----------+--------------+--------+
    |          1 | aaa       |            1 |  11576 |
    |          2 | bbb       |            2 |  11576 |
    |          3 | ccc       |            3 |  11576 |
    +------------+-----------+--------------+--------+
    3 rows in set (0.00 sec)
    

    【讨论】:

    • 非常感谢!我正在缓慢但肯定地掌握这些概念,非常感谢!
    猜你喜欢
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多