CURSOR与更新

时间:2014-01-15 21:38:14

标签: sql sql-server cursor

公司使用SQL Server数据库来存储有关其客户及其业务事务的信息。为您的城市引入了新的区号。区号111对于前缀小于500的电话号码保持不变。前缀为500或更大的号码将被分配区号222.客户表中电话列中的所有电话号码都存储为char(12)以下格式的字符串,'999-999-9999'。我必须对Customers表进行适当的更改

尽快使用最少的管理工作。我应该使用哪一个?

一个。

UPDATE Customers SET Phone = ‘222-‘ + SUBSTRING(Phone,5,8) 
FROM Customers WHERE SUBSTRING(Phone,1,3) = ‘111’ 
AND SUBSTRING(Phone,5,3) >= 500 

DECLARE PhoneCursor CURSOR FOR 
   SELECT Phone FROM Customers 
   WHERE SUBSTRING(Phone,1,3) = 111 
     AND SUBSTRING(Phone,5,3) >= 500 

OPEN PhoneCursor 
FETCH NEXT FROM PhoneCursor 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    UPDATE Customers 
    SET Phone = ‘222’ + SUBSTRING(Phone,5,8) 
    WHERE CURRENT OF PhoneCursor 

    FETCH NEXT FROM PhoneCursor 
END 

CLOSE PhoneCursor 
DEALLOCATE PhoneCursor 

2 个答案:

答案 0 :(得分:1)

大更新将持有针对数据库的事务,可能需要很长时间......锁定并造成各种破坏。

为此,我建议使用光标在一段时间内传播该负载。

我还做了一个'chunked'更新......就像这样:

DECLARE @Done bit = 0
WHILE @Done = 0
BEGIN
    UPDATE TOP(10000)
        Customers SET Phone = ‘222-‘ + SUBSTRING(Phone,5,8) 
    FROM Customers WHERE SUBSTRING(Phone,1,3) = ‘111’ 
    AND SUBSTRING(Phone,5,3) >= 500 

    IF @@ROWCOUNT = 0
    BEGIN
        SET @Done = 1
    END
END

答案 1 :(得分:1)

在任何大型数据集中光标都会慢得多,谈论几秒钟或几毫秒。它的作用是不会在任何时候将数据库与其他用户锁定一段时间。

这就是为什么对于大型数据集,批处理方法可能是最好的。

一般情况下,我会首先尝试基于集合的方法,如果需要,可以在非工作时间运行。然后我会尝试基于集合的方法,只有在基于集合的速度太慢的情况下才会运行一批记录。

如果你必须光标运行一条记录,那么你的数据库设计可能会出现严重错误。游标通常是最后的手段。不要将它们用于插入/更新或删除。