我們從上述的代碼中可以看到,在我們取出來表的記錄集的時候,然後通過滿足條件的記錄集在程序中循環的去傳條件進行數據的插入的操作。
如果數據量少可能看不出用上面這種辦法實現的弱點,因爲它每次在操作數據庫的時候,都存在着頻繁的和數據庫的I/O直接交互,這點性能的犧牲實屬不應該,那我們就看下面的方法,通過存儲過程的遊標方法來實現:
建立存儲過程:
Create PROCEDURE P_InsertSubject @SubjectId int AS DECLARE rs CURSOR LOCAL SCROLL FOR select studentid from student where StudentGradu = 1
OPEN rs FETCH NEXT FROM rs INTO @tempStudentID WHILE @@FETCH_STATUS = 0 BEGIN Insert SelSubject values (@SubjectId,@tempStudentID) FETCH NEXT FROM rs INTO @tempStudentID END CLOSE rs GO |
使用遊標對記錄集循環進行處理的時候一般操作如以下幾個步驟:
1、把記錄集傳給遊標;
2、打開遊標
3、開始循環
4、從遊標中取值
5、檢查那一行被返回
6、處理
7、關閉循環
8、關閉遊標
上面這種方法在性能上面無疑已經是提高很多了,但我們也想到,在存儲過程編寫的時候,有時候我們儘量少的避免使用遊標來進行操作,所以我們還可以對上面的存儲過程進行改造,使用下面的方法來實現:
Create PROCEDURE P_InsertSubject @SubjectId int AS declare @i int, @studentid
DECLARE @tCanStudent TABLE ( studentid int ,FlagID TINYINT )
BEGIN insert @tCanStudent select studentid,0 from student where StudentGradu = 1 SET @i=1 WHILE( @i>=1) BEGIN SELECT @studentid=''
SELECT TOP 1 @studentid = studentid FROM @tCanStudent WHERE flagID=0 SET @i=@@ROWCOUNT IF @i<=0 GOTO Return_Lab Insert SelSubject values (@SubjectId,@studentid) IF @@error=0 UPDATE @tCanStudent SET flagID=1 WHERE studentid = @studentid Return_Lab: END End GO
|
我們現在再來分析以上這個存儲過程,它實現的方法是先把滿足條件的記錄集數據存放到一個表變量中,並且在這個表變量中增加一個FLAGID進行數據初始值爲0的存放,然後去循環這個記錄集,每循環一次,就把對應的FLAGID的值改成1,然後再根據循環來查找滿足條件等於0的情況,可以看到,每循環一次,處理的記錄集就會少一次,然後循環的往選好課程表裏面插入,直到記錄集的條數爲0時停止循環,此時完成操作。
比較以上的幾種循環方法的應用,就會知道,有時候可能對於同一種功能我們實現的方法不同,而最終應用程序性能的影響的差異就會很大,第二種、第三種就大大的減少的數據庫交互I/O操作的頻繁,會節省很多時間,方法三又避免用遊標又可以節省不必要的開銷。