【问题标题】:Stuck to Create Cursor坚持创建光标
【发布时间】:2016-05-09 15:50:38
【问题描述】:

我想更新我的价值工资。

例如,如果@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;

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

【问题讨论】:

  • 它有几个问题,但我不得不问,你为什么要为此使用cursor
  • 因为每个员工都有不同的工作时间,所以我用它来更新我的 DB @Lamak 中每个员工的工资
  • 光标是完全没有必要的,你甚至可以看到你没有在更新中使用员工姓名,所以它每次都会更新该性别的每一位员工(这将是正确的做法它,根本没有光标)
  • 好的,用一套基本解决方案发布了答案
  • 我强烈建议不要以明文形式存储 ssn...这是高度敏感的数据,应始终加密。

标签: sql-server stored-procedures cursor


【解决方案1】:

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

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;

【讨论】:

  • 谢谢先生,很有帮助,我只是学习sqlserver,我的知识还不够好......
【解决方案2】:

您没有在循环内获取,所以它只是一遍又一遍地使用相同的值。只需在循环内重复您的 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

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

【讨论】:

  • 但这不需要光标。这是一个单一的更新语句,通过引入循环变成了不必要的慢。并且每次经过都会更新表中的每一行。
【解决方案3】:

只是为了在此处提供另一个选项,您可以使用 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

【讨论】:

    猜你喜欢
    • 2020-06-07
    • 2011-12-07
    • 2017-04-12
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2014-12-26
    • 2014-11-27
    相关资源
    最近更新 更多