2012-04-05 14 views
3

要するに、私は1つの文字列に対して複数の置換を実行できる単一の再帰的なクエリを探しています。私はそれを行うことができるという考えを持っていますが、私の頭をそれのまわりで包んでいません。再帰的な文字のテーブルからの置換

私はアプリケーションのbiz-layer、またはCLRでも置き換えを行うことをお勧めしますが、この場合はオプションではありません。

具体的には、私は以下の混乱を取り除いています - これは8種類のストアドプロシージャでC & Pです - TVFで置き換えてください。 - 「 - 」が1になることはありません(と知っ「」私はで区切られた単一の文字列にすべての問題の文字に参加した

-- 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 

お知らせ:私が始めたのはここ

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 

です違反している文字の中から)、分割されます。このクエリの結果は次のようになります。だから、

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 

1つのクエリでこれを達成する方法に関するアイデアはありますか?

編集:別の方法がある場合は、実際の再帰は必要ありません。私はここでも数字のテーブルの使用を熟考しています。

答えて

4

スカラー関数で使用できます。私はそれを使用して、いくつかの外部入力からすべての制御文字を削除します。

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

これは、私が提供している畳み込み再帰CTEよりも優れています。私はそれが完全な意味を成し遂げても、SQLがTの各行の@targetの価値を再評価することは明らかではないと思います。 – Griffin

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 

まだ、私は他の提案があります。

関連する問題