我想知道您在使用現有代碼中的SQL Server遊標替換過程中的體驗,或者您如何解決程序員使用遊標解決問題的方法,以及它是否基於set-based。更換光標有哪些不同的方法?
光標被用來解決什麼問題?你是如何替換光標的?
我想知道您在使用現有代碼中的SQL Server遊標替換過程中的體驗,或者您如何解決程序員使用遊標解決問題的方法,以及它是否基於set-based。更換光標有哪些不同的方法?
光標被用來解決什麼問題?你是如何替換光標的?
嘗試永不循環,處理數據集。
您可以一次插入,更新,刪除多行。這裏插入一個多行示例:
INSERT INTO YourTable
(col1, col2, col3, col4)
SELECT
cola, colb+Colz, colc, @X
FROM ....
LEFT OUTER JOIN ...
WHERE...
當看一個循環時,看看它在裏面做了什麼。如果只是插入/刪除/更新,請重新編寫以使用單個命令。如果有IF,請查看它們是否可以是CASE語句或WHERE條件插入/刪除/更新。如果是這樣,請刪除循環並使用set命令。
我採取了循環,並用基於集合的命令替換它們,並將執行時間從幾分鐘減少到幾秒鐘。我已經採用了許多嵌套循環和過程調用的過程,並保留了循環(不可能只使用插入/刪除/更新),但我刪除了光標,並且看到鎖定/阻塞較少,並且性能大幅提升。這裏有兩個循環的方法是優於光標循環...
,如果你有循環,在一組做這樣的事情:
--this looks up each row for every iteration
DECLARE @msg VARCHAR(250)
DECLARE @hostname sysname
--first select of currsor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
WHILE @hostname is not null
BEGIN
set @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(@hostname) + ' '
+ 'testing "'
print @msg
--EXEC (@msg)
--next select of cursor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
and hostname > @hostname
END
,如果你有一個合理的組項目(不十萬)來循環你可以這樣做:
--this will capture each Key to loop over
DECLARE @msg VARCHAR(250)
DECLARE @From int
DECLARE @To int
CREATE TABLE #Rows
(
RowID int not null primary key identity(1,1)
,hostname varchar(100)
)
INSERT INTO #Rows
SELECT DISTINCT hostname
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
SELECT @From=0,@[email protected]@ROWCOUNT
WHILE @From<@To
BEGIN
SET @[email protected]+1
SELECT @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(hostname) + ' '
+ 'testing "'
FROM #Rows WHERE [email protected]
print @msg
--EXEC (@msg)
END
那麼,通常一個用於程序編程的應用程序開發者將不再習慣 - 儘量以程序化方式處理所有事情,即使在SQL中也是如此。
大多數情況下,具有正確參數的SELECT可能會執行 - 或者您正在處理UPDATE語句。
問題的關鍵在於:您需要開始在集合操作中思考並告訴RDBMS您想要完成的任務 - 而不是一步一步地完成。
很難給出一個「正確的」答案......你幾乎不得不用一個具體的例子來展示它。
Marc
我寫了一些代碼來計算與給定年份相關的財務數據的運行總計。在每個季度,我必須將當前季度的值添加到運行總計,同時適當地處理NULL,以便在當前季度的值爲NULL時延續上個季度的運行總計。
最初,我是用光標做的,從功能的角度來看,這符合業務需求。從技術角度來看,它變成了一個表演停止者,因爲隨着數據量的增加,代碼的指數時間變長了。解決方案是用滿足功能要求的相關子查詢替換遊標,並消除任何性能問題。
希望這有助於
比爾
我已經更換了一些光標與WHILE循環。
DECLARE @SomeTable TABLE
(
ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
SomeNumber int,
SomeText varchar
)
DECLARE @theCount int
DECLARE @theMax int
DECLARE @theNumber int
DECLARE @theText varchar
INSERT INTO @SomeTable (SomeNumber, SomeText)
SELECT Number, Text
FROM PrimaryTable
SET @theCount = 1
SELECT @theMax = COUNT(ID) FROM @SomeTable
WHILE (@theCount <= @theMax)
BEGIN
SET @theNumber = 0
SET @theText = ''
SELECT @theNumber = IsNull(Number, 0), @theText = IsNull(Text, 'nothing')
FROM @SomeTable
WHERE ID = @theCount
-- Do something.
PRINT 'This is ' + @theText + ' from record ' + CAST(@theNumber AS varchar) + '.'
SET @theCount = @theCount + 1
END
PRINT 'Done'