Gri*_*fin 4 t-sql recursion sql-server-2005
简而言之,我正在寻找可以对一个字符串执行多次替换的单个递归查询。我有一个想法是可以做到的,但我无法理解它。
当然,我更喜欢应用程序的商业层,甚至是 CLR,来进行替换,但在这种情况下,这些不是选项。
更具体地说,我想用 TVF 替换下面的混乱 - 这是 8 个不同存储过程中的 C&P。
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
Run Code Online (Sandbox Code Playgroud)
这是我开始的地方:
-- 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('A~B!C@D@C!B~A', MM.ELEMENT, '-') TGT
FROM dbo.tvf_SplitString('~-''-!-@-#', '-') MM
Run Code Online (Sandbox Code Playgroud)
请注意,我已将所有有问题的字符连接到一个由 '-' 分隔的字符串中(知道 '-' 永远不会是有问题的字符之一),然后将其拆分。此查询的结果如下所示:
TGT
------------
A-B!C@D@C!B-A
A~B!C@D@C!B~A
A~B-C@D@C-B~A
A~B!C-D-C!B~A
A~B!C@D@C!B~A
Run Code Online (Sandbox Code Playgroud)
所以,替换显然有效,但现在我希望它是递归的,这样我就可以拉出前 1 并最终得出:
TGT
------------
A-B-C-D-C-B-A
Run Code Online (Sandbox Code Playgroud)
关于如何通过一个查询完成此任务的任何想法?
编辑:好吧,如果有另一种方式,则不需要实际递归。我也在考虑在这里使用数字表。
您可以在标量函数中使用它。我用它从一些外部输入中删除所有控制字符。
SELECT @target = REPLACE(@target, invalidChar, '-')
FROM (VALUES ('~'),(''''),('!'),('@'),('#')) AS T(invalidChar)
Run Code Online (Sandbox Code Playgroud)
我想到了。我没有提到 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('A~B!C@D@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('~-''-!-@-#', '-') MM
WHERE XX.RN = MM.pos)
SELECT TOP 1 XX.TGT
FROM XX
ORDER BY RN DESC
Run Code Online (Sandbox Code Playgroud)
尽管如此,我仍愿意接受其他建议。