如何在函数内正确编写游标?
How to properly write a cursor inside a function?
我有点迷路了,需要你的帮助。我试图查看 google 函数中的游标和有关这些游标的参考资料,但我似乎无法完全理解这个概念。我有一个作业需要做:
- 创建一个我在其中使用游标的函数
- 条目是工资增长的百分比(例如:5% 是 0.05)
- 函数需要用新增加的价格更新工资
- 显示新的平均工资
- 并处理可能的错误
这是我到目前为止所做的...
你能用提示或至少简单的 examples/ressources 函数中的游标帮助我解决这个问题吗?这样我就可以开始更好地掌握这个概念了。
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 ;
如果您使用游标,则必须从游标中 FETCH(请查看 https://dev.mysql.com/doc/refman/8.0/en/fetch.html)而不进行 fetch 循环是无限的。 AVG 是一个聚合函数,你不能对游标进行 AVG(你需要一个 select..from)。每次迭代游标循环时,您的更新语句将应用于所有员工(逻辑上荒谬)。就我个人而言,我永远不会使用函数,因为你正在尝试做的事情在函数中并不合适(我会使用过程)。
一个'working'但错误函数的例子
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)
我有点迷路了,需要你的帮助。我试图查看 google 函数中的游标和有关这些游标的参考资料,但我似乎无法完全理解这个概念。我有一个作业需要做:
- 创建一个我在其中使用游标的函数
- 条目是工资增长的百分比(例如:5% 是 0.05)
- 函数需要用新增加的价格更新工资
- 显示新的平均工资
- 并处理可能的错误
这是我到目前为止所做的...
你能用提示或至少简单的 examples/ressources 函数中的游标帮助我解决这个问题吗?这样我就可以开始更好地掌握这个概念了。
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 ;
如果您使用游标,则必须从游标中 FETCH(请查看 https://dev.mysql.com/doc/refman/8.0/en/fetch.html)而不进行 fetch 循环是无限的。 AVG 是一个聚合函数,你不能对游标进行 AVG(你需要一个 select..from)。每次迭代游标循环时,您的更新语句将应用于所有员工(逻辑上荒谬)。就我个人而言,我永远不会使用函数,因为你正在尝试做的事情在函数中并不合适(我会使用过程)。
一个'working'但错误函数的例子
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)