MySql中的存储过程和游标

时间:2014-04-29 12:19:04

标签: mysql

我有两个表,员工和部门。他们看起来像这样:

Employee
Name
SSN
DeptID
Salary

Department
DName
DId
Total_Sal

Department.total_sal是属于该部门的所有员工薪水的总和。我需要一个存储过程,它利用游标迭代每个员工,并更新相应部门的工资。我之前从未使用过游标或存储过程,我对如何遍历一个表但更新另一个表有点困惑。任何帮助/建议表示赞赏。

另一个快速的问题,我喜欢在SQLFIDDLE中完成我的所有SQL工作,是否有人知道它是否也支持存储过程/游标?

这是我的第一次尝试,我想在此开头擦除Department.Total_sal是个好主意?

DELIMITER //
DROP PROCEDURE IF EXISTS cur_sal

CREATE PROCEDURE cur_sal
  BEGIN
    DECLARE e_sal, e_dno INT;
    DECLARE d_sal, d_dno INT;
    DECLARE cur_emp CURSOR FOR SELECT salary, DeptId FROM employee;
    DECLARE cur_dep CURSOR FOR SELECT DId, Total_sal FROM department;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cur_emp;
    OPEN cur_dep;


    r_loop: LOOP
      FETCH cur_emp INTO e_sal, e_dno;
      FETCH cur_dep INTO d_sal, d_dno;
      IF done THEN
        LEAVE r_loop;
      END IF;

      IF e_dno = d_dno THEN
        UPDATE department SET total_sal = total_sal + e_sal;
      END IF;
    END LOOP;

    CLOSE cur_emp;
    CLOSE cur_dep;
  END //

3 个答案:

答案 0 :(得分:2)

没有必要使用游标来执行此操作。有多种方法可以实现相同的结果,包括连接和子选择。在下面的代码中,我使用了一个子选择(因为我必须回去工作并且很快):

将其放入Build Scheme部分:

-- create the tables
CREATE TABLE Employee 
    (
    Name varchar(50),
    SSN varchar(50),
    DeptID int,
    Salary float
    );

CREATE TABLE Department 
    (
    DName varchar(50),
    DId int,
    Total_Sal float
    );

-- insert default values
insert into Employee (name,ssn,deptid,salary)
values('Mr Test', '12345a', 1,10000);

insert into Employee (name,ssn,deptid,salary)
values('Mr Tester', '12345b', 1,33000);

-- notice the total_sal is 63000
insert into department (DName, DID, total_sal)
values('Test department',1,63000);

-- now we update the total_sal to be the sum of everyone in that department
update Department 
set total_sal = (SELECT SUM(Salary) FROM employee where employee.DeptID = Department.DID)

在可执行部分中运行:

select * from department

你会注意到total_sal现在是43000而不是插入的初始63000值。

我使用的更新语句会遍历每个部门。

这是SQLFiddle:SQLFiddle

如果您坚持使用光标,您可以采取以下措施:

CREATE PROCEDURE UpdateSalaries()
BEGIN

  -- Cursor Example
  declare DeptID INTEGER;
  declare TotalSalary FLOAT;

  declare SalaryCursor Cursor for select DId, 
    (SELECT SUM(Salary) FROM employee where employee.DeptID = Department.DID) from department

    DECLARE CONTINUE HANDLER 
    FOR NOT FOUND SET finished = 1;

    open SalaryCursor
      FETCH SalaryCursor INTO DeptID, TotalSalary;

    get_Salary: LOOP

      update Department 
      set total_sal = TotalSalary
      WHERE DID = DeptID

    END LOOP get_Salary;

  CLOSE SalaryCursor;
END

答案 1 :(得分:1)

CREATE PROCEDURE cur_sal
  BEGIN
    DECLARE e_sal, e_dno INT;
    DECLARE sum_sal INT
    DECLARE d_sal, d_dno INT;
    DECLARE cur_emp CURSOR FOR SELECT salary, Dno FROM employee;
    DECLARE cur_dep CURSOR FOR SELECT Dno, Total_sal FROM department;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cur_emp;
    OPEN cur_dep;


    r_loop: LOOP
      FETCH cur_emp INTO e_sal, e_dno;
      FETCH cur_dep INTO d_sal, d_dno;
      IF done THEN
        LEAVE r_loop;
      END IF;

      IF e_dno = d_dno THEN
         SET sum_sal = sum_sal + e_sal;
      END IF;
    END LOOP;
UPDATE department SET total_sal = sum_sal where DId = Dno;
    CLOSE cur_emp;
    CLOSE cur_dep;
  END //

这里你非常接近我认为,你想使用一个临时变量来保存所有事务的总和,直到你到达循环结束。当您到达最后时,您将使用总计值更新部门薪资。我刚刚使用了sum_sal。

更新语句需要一个where子句,你基本上会把你的光标充满你的

答案 2 :(得分:0)

您可以从中获得帮助:

Cursor in MySQL stored procedures