2014-02-12 62 views
1

我讀了一個答案,表示你不想在SQL Server中使用WHILE循環。我不明白這個泛化。我對SQL相當陌生,所以我可能還不瞭解解釋。我還讀到,除非必須,否則你並不真的想使用遊標。我發現的搜索結果對所提出的問題過於具體,我無法從他們那裏收集有用的技術,因此我將此呈現給您。Sql Server 2008 R2使用函數內部的WHILE循環

我想要做的是採取客戶端文件中的值,並在必要時縮短它們。這裏需要實現一些事情。我不能簡單地破解提供的字段值。我的公司有使用的標準縮寫。我把這些放在一張表中,縮寫。該表具有LongNameShortName。我不想簡單地縮寫行中的每個LongName。只要字段長度過長,我只想應用更新。這就是爲什麼我需要WHILE循環。

我的思維過程是這樣的:

CREATE FUNCTION [dbo].[ScrubAbbrev] 
(@Field nvarchar(25),@Abbrev nvarchar(255)) 
RETURNS varchar(255) 
AS 
BEGIN 
    DECLARE @max int = (select MAX(stepid) from Abbreviations) 
    DECLARE @StepID int = (select min(stepid) from Abbreviations) 
    DECLARE @find varchar(150)=(select Longname from Abbreviations where [email protected]) 
    DECLARE @replace varchar(150)=(select ShortName from Abbreviations where [email protected]) 
    DECLARE @size int = (select max_input_length from FieldDefinitions where FieldName = 'title') 
    DECLARE @isDone int = (select COUNT(*) from SizeTest where LEN(Title)>(@size)) 

    WHILE @StepID<[email protected] or @isDone = 0 and LEN(@Abbrev)>(@size) and @Abbrev is not null 
    BEGIN 
     RETURN 
     REPLACE(@Abbrev,@find,@replace) 
     SET @[email protected]+1 
     SET @find =(select Longname from Abbreviations where [email protected]) 
     SET @replace =(select ShortName from Abbreviations where [email protected]) 
     SET @isDone = (select COUNT(*) from SizeTest where LEN(Title)>(@size)) 
    END 
END 

顯然RETURN應該走在最後,但我需要給我的變量重置到下一@stepID@find@replace

這是我必須使用遊標(我從來沒有寫過)的那些時間之一?

回答

1

通常,您不希望在SQL中使用遊標或while循環,因爲它們一次只處理一行,因此性能很差。 SQL被設計和優化以處理(可能非常大的)數據集,而不是單個值。

你可以做這樣的事情分解出while循環:

UPDATE t 
SET t.targetColumn = a.ShortName 
FROM targetTable t 
INNER JOIN Abbreviations a 
ON t.targetColumn = a.LongName 
WHERE LEN(t.targetColumn) > @maxLength 

這是廣義的,你將需要調整以滿足您的特定的數據模型,但在這裏是怎麼回事:

對於「targetTable」中的每一行,將「targetColumn」(您想要縮寫的)的值設置爲相關縮寫(在Abbreviations.ShortName中找到)iff:當前值具有標準化縮寫(內部連接)和當前值比期望的更長(where條件)。

您需要添加一個整型參數或局部變量@maxLength來指示「太長」的構成。此查詢一次處理目標表,爲每個符合條件的行更新目標列中的值,而函數一次只能找到單個項目的縮寫(一行一列)。

請注意,如果值太長,但沒有標準縮寫,則不會執行任何操作。您現有的代碼具有相同的限制,所以我認爲這是所需的行爲。

我也建議使這個存儲過程,而不是一個函數。 SQL Server上的函數被視爲黑盒子,並且會嚴重損害性能,因爲優化器通常不知道他們在做什麼。

+0

我明白你在說什麼,因爲任何必須評估每一行的東西都是一個重要的過程。這是聯繫信息,所以我必須根據它的可用長度將它應用於每個字段。另外,我無法取代整個領域。 我期望實現的是將「生物統計學研究副教授」轉變爲「UBC部門病理學與實驗醫學教授」這就是爲什麼我使用'REPLACE'功能而不是'SET'。 –

+0

當然,有道理。看起來您每個條目也可能有多個縮寫。在這種情況下,您希望加入像'%'+ LongName +'%'這樣的targetColumn,並在update語句中使用replace。可能需要進行一些調整以確保避免誤報(例如部分詞匹配),但通用技術是相同的:使用基於集合的方法來避免循環的性能問題。 –

+0

感謝您的幫助。我將在下週重新審視這個項目。顯然我還不能登入。 : -/ –