2013-09-16 32 views
13

是否有可能在不使用遊標的情況下爲選擇的每一行執行一些代碼?TSQL - 爲選擇的每一行執行代碼

在我的情況: 我有一個臨時表來存儲complexe腳本的一些數據。最後,我想將這張表的某些信息(受某些條件限制)輸出到輸出中。

目前我正在使用帶select的遊標來限制表的行。在這個遊標中,我正在使用

print '...' 

生成輸出。

必須有做這種事情更簡單的方法...

編輯:

create table #tmpAttributes(AttributeId uniqueidentifier, Value float, ValueString nvarchar(max), ActionId uniqueidentifier) 

insert into #tmpAttributes (AttributeId, Value, ValueString, ActionId) 
    select ID,..... -- in this select i'm doing some value conversions, if conversion is not possible i'm using -1 

insert into ActionAttribute (ActionDefinitionID, Discriminator, ID, ReferredActionID, ValueDate, ValueListID, ValueMoney, ValueString, ValueUserID) 
    select @defId, 'ActionAttributeMoneyEntity', NEWID(), ActionId, null, null, Value, null, null from #tmpAttributes 

-- afterwards there is this cursor where I'm printint all rows where Value = -1 
+2

沒有足夠的信息。你究竟在努力實現什麼?如果你給我們一個完整的場景,你可能會發現有一個完全基於集合的方式來執行你所需要的。 – gvee

+0

爲什麼不在剛剛創建的「臨時表」上放置一個額外的標識列,併爲每一行循環播放。 –

+0

如果你只是想打印這些信息「最後」,爲什麼你需要一個光標呢? – DrCopyPaste

回答

19

爲結果集中的每一行執行打印語句幾乎需要一個遊標或類似於此的方法

declare @id int, @stuff varchar(20) 
declare @tmp table 
(
    id int not null 
, stuff varchar(20) 

    primary key(id) 
) 

insert @tmp 
select id, stuff from mastertable 
where condition1 > condition2 

select top 1 @id=id, @stuff=stuff from @tmp 

while (@@rowcount > 0) 
begin 
    print @stuff 
    delete from @tmp where [email protected] 
    select top 1 @id=id, @stuff=stuff from @tmp 
end 

您仍在循環每行,但您避免了遊標。由於您使用的是表格變量而不是遊標,因此您可以避免表格鎖定,但這不一定是更好的方法。您可以按各種可能的方式逐行處理,例如添加「已處理列」或編號所有選定行1..n並基於rownumber迭代

您只能避免逐行處理if您可以執行基於集合的操作。在您的問題中沒有足夠的信息來查看這是否可以在TSQL中避免這種情況現在,編寫CLR過程可能會更靈活,因爲您擁有更豐富的編程模型,並且循環遍歷每行CLR過程中的結果集。使從CLR PROC數據庫調用的每一行每一行數據庫調用在TSQL

編輯 - 我看到有人已經添加了一種可能的方式轉換成打印語句爲一組化運作。即

declare @msg varchar(max) 
select @msg = '' 

select msg = @msg + stuff 
from mastertable where condition1 > condition2 

print @msg 

這是可以的,事實上,當我提到進行設置操作時,我指的是最佳的。如果可能,總是首選基於集合的操作。它可能不是很明顯,但是字符串連接還可以在這個例子中得到非常慢太多,如果多行參與。


我說過使用temp var可以避免表鎖定。這並不完全正確,因爲sql server會將臨時變量寫入tempdb中的表中。我真正的意思是,你避免鎖定生產表,因爲你保證是該表的唯一用戶,您沒有併發訪問的競爭。

我也沒有打算要做出優化此。例如,內環可以跟蹤id和其中條件變得其中id> @id(你也將要在ID所定義的主鍵)。由於臨時表在每次循環迭代過程中都沒有更新,我預計它會更快。

+0

仍是一個循環,但不使用「重」光標。謝謝! –

8

我認爲你需要提供更多的細節,但你可能會尋找類似:

declare @msg varchar(max)=''; 

select @msg = @msg + 'Output line: ' + ColumnA + ' -- ' + 'ColumnB' + char(13)+char(10) 
from #temp 
where ... 
; 

print @msg; 
+0

因此,對於每一行變量的值將被擴展......好主意! –

+0

確保添加'OPTION(MAXDOP 1)'以防止並行性,這會帶來意想不到的結果。 – gjvdkamp