Sql-Server
如何用多行數據替換字元串的多個部分?
- 這是一個小提琴來展示我所追求的。
給定一個包含兩列的表 - 一個整數 ID 和一個基於文本的字元串 - 我想從一個字元串值開始,該字元串值對包含在花括號中的任意數量的整數進行編碼,並與任何其他有效的文本字元混合。
例子:
'{1} / {9} ... {12}'
使用單個
SELECT
語句,我想返回一個字元串,其中所有整數(及其包裝大括號)都已替換為從我的表中派生的值;具體來說,具有與源字元串中找到的數字相匹配的 ID 的行的文本值……以及大括號外的任何字元保持不變。這是一個無法完成任務的範例:
select replace('{13} {15}','{'+cast(id as varchar)+'}',isNull(display,'')) from testing;
testing
這將在表中每行返回 1 行。對於id
value = 13 的行,字元串的“{13}”部分已成功替換,但“{15}”部分未成功替換(反之亦然,在第 15 行)。我想創建一個循環遍歷所有
testing
行並反复嘗試替換的函式將解決問題。儘管如此,直接的 SQL 語句將比循環更可取。範例數據
+----+-------------------+ | id | display | +----+-------------------+ | 1 | Apple | | 2 | Banana | | 3 | Celery | | 4 | Dragonfruit | | 5 | Eggplant | | 6 | Fenugreek | | 7 | Gourd | | 8 | Honeydew | | 9 | Iceberg Lettuce | | 10 | Jackfruit | | 11 | Kale | | 12 | Lemon | | 13 | Mandarin | | 14 | Nectarine | | 15 | Olive | +----+-------------------+
範例案例
select replace('{1} {3}',null,null) -- Returns 'Apple Celery' select replace('{3},{4},{5}',null,null); -- Returns 'Celery,Dragonfruit,Eggplant' select replace('{1} / {9} ... {12}',null,null); -- Returns 'Apple / Iceberg Lettuce ... Lemon'
顯然,
replace
關鍵字不起作用。PS。如果解決方案需要更改字元串的格式以促進這一點,那麼這是一種選擇。
例如:(
'#1 / #9 ... #12'
與前面的範例相關)在這種格式中,也許我們可以將字元串分解為一個行集,基於
#
,取left
字元直到我們找到一個非數字,根據取的數字join
到表中,用表的值testing
替換#
和 數字然後所有這些單獨將標記修改回單個字元串?testing``display``stuff``for xml path
我正在使用不支持的 SQL Server 2016
string_agg
。也就是說,如果有使用 的解決方案string_agg
,我仍然有興趣查看它。
這是使用遞歸
cte
轉換變數的範例drop table if exists testing; go create table testing (id int, display varchar(16)); insert into testing values (1, 'Apple'); insert into testing values (2, 'Banana'); insert into testing values (3, 'Celery'); insert into testing values (4, 'Dragonfruit'); insert into testing values (5, 'Eggplant'); DROP FUNCTION IF EXISTS dbo.TranslateVariables go CREATE FUNCTION dbo.TranslateVariables ( @StringValue VARCHAR(MAX) ) RETURNS TABLE AS RETURN ( --Common Table Expression for Translation WITH TranslationTable AS ( SELECT FindValue = '{' + convert(varchar(5),id) + '}' ,ReplaceValue = display,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn FROM testing ) --Recursive CTE to loop through the TranslationTable and replace FindValue with ReplaceValue ,RecursiveCte as ( SELECT @StringValue AS StrValue ,( SELECT count(*) FROM TranslationTable ) AS cnt UNION ALL SELECT replace(StrValue, tt.FindValue, tt.Replacevalue) ,cnt - 1 FROM RecursiveCte JOIN TranslationTable tt ON tt.rn = cnt ) SELECT StrValue ,cnt FROM RecursiveCte where cnt = 0 ) go
--Verify translation SELECT * FROM dbo.TranslateVariables('{1} {3}') OPTION (MAXRECURSION 32767) -- Don't forget to use the maxrecursion option!
StrValue | cnt | |--------------|-----| | Apple Celery | 0 |
SELECT * FROM dbo.TranslateVariables('{3},{4},{5}') OPTION (MAXRECURSION 32767) -- Don't forget to use the maxrecursion option!
| StrValue | cnt | |-----------------------------|-----| | Celery,Dragonfruit,Eggplant | 0 |