2019年1月29日 星期二

用Temp Table取代Cursor

cursor通常用來逐筆處理資料使用,下面是一個簡單的範例(MS SQL Server 2008)
  1. declare @myId int
  2. declare @myName nvarchar(20)
  3. declare @myCursor CURSOR
  4.  
  5. set @myCursor = CURSOR FAST_FORWARD
  6. FOR
  7. SELECT ID, NAME FROM Employee
  8. open @myCursor
  9. INTO @myId, @myName
  10. WHILE @@FETCH_STATUS = 0
  11. BEGIN
  12.  
  13. --DO SOMETHING
  14.  
  15. FETCH NEXT FROM @myCursor
  16. INTO @myId, @myName
  17.  
  18. END
  19.  
  20. CLOSE @myCursor
  21. DEALLOCATE @myCursor
用temp table來模擬cursor的操作模式,簡單的說就是把SELECT ID, NAME FROM Employee的結果存到temp table中,在逐步讀取,所以必須先建立一個temp table如下
  1. create table #tempEmployee
  2. (
  3. ID int,
  4. NAME nvarchar(20)
  5. )
然後把資料insert into select 到 #tempEmployee
  1. insert into #tempEmployee (ID,NAME)
  2. select ID,NAME
  3. from Employee
接下來,就是逐步讀取這個temp table #tempEmployee
在MS SQL Server中使用SET ROWCOUNT 1來控制select時一次只撈出一筆資料,而且每做完一筆就刪掉,直到#tempEmployee沒有資料為止
  1. declare @countTemp int --用來計算#tempEmployee還剩幾筆資料
  2.  
  3. --計算#tempEmployee資料數
  4. select @countTemp = count(*) from #tempEmployee
  5.  
  6. while(@countTemp > 0)
  7. begin
  8. set rowcount 1
  9. select @myId = ID, @myName = NAME from #tempEmployee
  10. --To Something
  11. --因為set rowcount 1的關係,所以一次只會刪一筆
  12. delete from #tempEmployee
  13.  
  14. --計算還剩幾筆,@countTemp > 0繼續
  15. select @countTemp = count(*) from #tempEmployee
  16. end
  17.  
  18. --#刪除 tempEmployee
  19. drop table #tempEmployee
  20.  
  21. --把select的預設比數恢復正常
  22. set rowcount 0
如此一般,完整的程式碼如下
  1. declare @myId int
  2. declare @myName nvarchar(20)
  3.  
  4. create table #tempEmployee
  5. (
  6. ID int,
  7. NAME nvarchar(20)
  8. )
  9.  
  10. declare @countTemp int --用來計算#tempEmployee還剩幾筆資料
  11.  
  12. --計算#tempEmployee資料數
  13. select @countTemp = count(*) from #tempEmployee
  14.  
  15. while(@countTemp > 0)
  16. begin
  17. set rowcount 1
  18. select @myId = ID, @myName = NAME from #tempEmployee
  19. --To Something
  20. --因為set rowcount 1的關係,所以一次只會刪一筆
  21. delete from #tempEmployee
  22.  
  23. --計算還剩幾筆,@countTemp > 0繼續
  24. select @countTemp = count(*) from #tempEmployee
  25. end
  26.  
  27. --#刪除 tempEmployee
  28. drop table #tempEmployee
參考資料/來源: 遜砲賴的爆肝筆記-stored procedure中不使用cursor逐步讀取資料列的方法

沒有留言:

張貼留言