一、遊標html
二、While循環post
咱們來了解下這兩種方案處理1w行數據分別須要多長時間。code
1、遊標。htm
首先咱們填充一個表,用優雅的遞歸方式填充。blog
create table Orders(OrderID int,CostValue decimal(18,2) ) ;with cte_temp as ( select 1 as OrderID union all select OrderID+1 from cte_temp where OrderID<10000 ) insert into Orders(OrderID) select OrderID from cte_temp option (maxrecursion 32767);
如今咱們的訂單表Orders有了一萬條訂單,可是CostValue仍是NULL值。遞歸
咱們用遊標的方式給每一條訂單添加一個CostValue,耗時44s。ci
--遊標 DECLARE @OrderID int DECLARE cursor_CostValue CURSOR FOR SELECT OrderID FROM Orders OPEN cursor_CostValue FETCH NEXT FROM cursor_CostValue INTO @OrderID WHILE @@FETCH_STATUS = 0 BEGIN UPDATE Orders SET CostValue = OrderID+100 WHERE OrderID = @OrderID FETCH NEXT FROM cursor_CostValue INTO @OrderID END CLOSE cursor_CostValue DEALLOCATE cursor_CostValue
2、While循環it
將數據放在臨時表中,而後操做臨時表,最後更新回總表。耗時16s。io
DECLARE @RowID int -- 獲取待處理的數據記錄到臨時表 -- 字段說明:RowID:記錄行號 / DealFlg:行處理標識 SELECT RowID = IDENTITY(INT , 1, 1),DealFlg=0,OrderID,CostValue = 0 INTO #Tmp FROM Orders SELECT @RowID = MIN(RowID) FROM #Tmp WHERE DealFlg = 0 -- 若最小行號不爲空(有須要處理的數據) WHILE @RowID IS NOT NULL BEGIN UPDATE #Tmp SET DealFlg = 1,CostValue=OrderID+100 WHERE RowID = @RowID SELECT @RowID = MIN(RowID) FROM #Tmp WHERE DealFlg = 0 END update O set O.CostValue=T.CostValue from Orders O inner join #Tmp T on O.OrderID=T.OrderID
還有一種錯誤的While循環,即不把數據放在臨時表中,直接操做本表,會大大增長耗時。table
由於屢次調用本表,若是在生產環境,將是一個災難。
DECLARE @OrderID INT --表中OrderID最小的值 SELECT @OrderID = MIN(OrderID) FROM Orders where CostValue is null WHILE @OrderID IS NOT NULL BEGIN UPDATE Orders SET CostValue = OrderID+100 WHERE OrderID = @OrderID SELECT @OrderID = MIN(OrderID) FROM Orders where CostValue is null END