坚持创造光标

时间:2016-05-09 15:50:39

标签: sql-server stored-procedures cursor

我想更新我的价值工资。

例如,如果@sex ='F',则只有具有性别F的员工将被更新,而另一名员工将与以前相同

ALTER procedure spEmployeeJamKerja (@sex varchar(1))
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @temp int
    DECLARE @fname nvarchar(20)

    DECLARE femaleEmpCursor CURSOR FOR
        SELECT e.fname, SUM(W.hours) AS TOTAL
        FROM employee e, works_on w
        WHERE e.sex = @sex AND e.ssn = W.ssn
        GROUP BY e.ssn,e.fname

    OPEN femaleEmpCursor

    FETCH NEXT FROM femaleEmpCursor INTO @fname, @temp

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF(@temp > 20)
        BEGIN
            UPDATE employee
            SET salary = salary + (@temp*5)
            WHERE sex = @sex
        END
        ELSE IF (@temp <= 20)
        BEGIN
            UPDATE employee
            SET salary = salary + ((@temp-1)*4)
            WHERE sex = @sex
        END 
    END
END

CLOSE femaleEmpCursor;
DEALLOCATE femaleEmpCursor;

在我尝试存储过程之后,查询永远不会停止,就像无限循环一样。有什么建议可以解决这个问题吗?

3 个答案:

答案 0 :(得分:2)

您绝对不需要光标,有不同的基于集合的方法来解决您的问题。这是另一种选择:

UPDATE e
SET e.salary =  e.salary + 
                CASE 
                    WHEN Total > 20 THEN Total*5 
                    WHEN Total <= 20 THEN (Total -1)*4
                END
FROM employee e
INNER JOIN (SELECT ssn, SUM([hours]) Total 
            FROM works_on
            GROUP BY ssn) w
    ON e.ssn = w.ssn
WHERE sex = @sex;

答案 1 :(得分:1)

你没有在循环内取得,所以它只是一遍又一遍地使用相同的值。只需在循环中重复你的fetch语句。

FETCH NEXT FROM femaleEmpCursor INTO @fname,@temp
    WHILE @@FETCH_STATUS = 0
        BEGIN
            IF(@temp>20)
            BEGIN
                UPDATE employee
                SET salary = salary + (@temp*5)
                WHERE sex = @sex
            END
        ELSE IF (@temp<=20)
        BEGIN
            UPDATE employee
            SET salary = salary + ((@temp-1)*4)
            WHERE sex = @sex
        END </pre>

        FETCH NEXT FROM femaleEmpCursor INTO @fname,@temp
    END

可能有更好的方法,但我认为这回答了这个问题。

答案 2 :(得分:0)

只是为了提供另一种选择,这是另一种方法,你可以使用cte。

with EmployeeData as
(
    select SUM(W.hours) AS TOTAL
        , e.ssn
    from employee e
    join works_on w on e.ssn = W.ssn
    where e.sex = @sex 
    group by e.ssn
        ,e.fname
)

update e
    set salary = 
        Case when ed.Total > 20 
            then salary + (ed.Total * )
        else salary + ((ed.Total - 1) * 4)
        end
from Employee e
join EmployeeData ed on ed.ssn = e.ssn
where e.sex = @sex