2012-04-05 76 views
3

簡而言之,我正在尋找一個可以對一個字符串執行多個替換的單個遞歸查詢。我有一個想法可以完成,但是我沒有把頭圍繞在它周圍。當然,我更喜歡應用程序的biz層,甚至是CLR來做替換,但在這種情況下這些不是選項。從字符表遞歸替換

更具體地說,我想用TVF替換下面的亂七八糟的東西 - 這是8個不同的存儲過程中的C &。

SET @temp = REPLACE(RTRIM(@target), '~', '-') 
SET @temp = REPLACE(@temp, '''', '-') 
SET @temp = REPLACE(@temp, '!', '-') 
SET @temp = REPLACE(@temp, '@', '-') 
SET @temp = REPLACE(@temp, '#', '-') 
-- 23 additional lines reducted 
SET @target = @temp 

這裏是我已經開始:

-- I have a split string TVF called tvf_SplitString that takes a string 
-- and a splitter, and returns a table with one row for each element. 
-- EDIT: tvf_SplitString returns a two-column table: pos, element, of which 
--  pos is simply the row_number of the element. 
SELECT REPLACE('[email protected]@C!B~A', MM.ELEMENT, '-') TGT 
FROM dbo.tvf_SplitString('~-''[email protected]#', '-') MM 

通知我參加了所有違規的字符到相隔一個字符串「 - 」(明知「 - 」永遠不會一個),然後分裂。從該查詢結果如下:

TGT 
------------ 
[email protected]@C!B-A 
[email protected]@C!B~A 
[email protected]@C-B~A 
A~B!C-D-C!B~A 
[email protected]@C!B~A 

所以,替換明確的工作,但現在我希望它是遞歸的,所以我可以拉頂部1,並最終推出了:

TGT 
------------ 
A-B-C-D-C-B-A 

有關如何使用一個查詢完成此任何想法?

編輯:好吧,如果還有其他方法,實際遞歸是不必要的。我也在想這裏使用數字表。

回答

4

您可以在標量函數中使用它。我用它從一些外部輸入中刪除所有控制字符。

SELECT @target = REPLACE(@target, invalidChar, '-') 
FROM (VALUES ('~'),(''''),('!'),('@'),('#')) AS T(invalidChar) 
+0

這比我提供的令人費解的遞歸CTE更好。我認爲SQL不會很明顯地重新評估T中每行的@target的值,儘管它確實很合理。 – Griffin 2016-01-26 17:14:07

4

我想通了。我沒有提到tvf_SplitString函數將行號作爲「pos」返回(儘管分配row_number的子查詢也可以工作)。有了這個事實,我可以控制遞歸調用和分割之間的交叉連接。

-- the cast to varchar(max) matches the output of the TVF, otherwise error. 
-- The iteration counter is joined to the row number value from the split string 
-- function to ensure each iteration only replaces on one character. 
WITH XX AS (SELECT CAST('[email protected]@C!B~A' AS VARCHAR(MAX)) TGT, 1 RN 
      UNION ALL 
      SELECT REPLACE(XX.TGT, MM.ELEMENT, '-'), RN + 1 RN 
      FROM XX, dbo.tvf_SplitString('~-''[email protected]#', '-') MM 
      WHERE XX.RN = MM.pos) 
SELECT TOP 1 XX.TGT 
FROM XX 
ORDER BY RN DESC 

不過,我接受其他建議。