我同意Gordon在應用程序代碼中最好處理這個問題。
如果無論出於何種原因,該選項不可用,並且如果您不希望按照Gordon的答案使用遞歸,則可以使用計數表方法來替換您的值。
您將需要測試,雖然每個值執行的for xml
的性能...
假設你有Tag
替換值表:
create table TagReplacementTable(Tag nvarchar(50), Replacement nvarchar(50));
insert into TagReplacementTable values('[test]',999)
,('[length]',75)
,('[height]',20)
,('[other length]',40)
,('[other height]',50);
您可以創建一個內嵌表功能將通過您的Descriptions
工作,並使用TagReplacementTable
作爲參考刪除替換必要的部件:
create function dbo.Tag_Replace(@str nvarchar(4000)
,@tagstart nvarchar(1)
,@tagend nvarchar(1)
)
returns table
as
return
(
with n(n) as (select n from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n(n))
-- Select the same number of rows as characters in @str as incremental row numbers.
-- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length.
,t(t) as (select top (select len(@str) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4)
-- Return the position of every value that starts or ends a part of the description.
-- This will be the first character (t='f'), the start of any tag (t='s') and the end of any tag (t='e').
,s(s,t) as (select 1, 'f'
union all select t+1, 's' from t where substring(@str,t,1) = @tagstart
union all select t+1, 'e' from t where substring(@str,t,1) = @tagend
)
-- Return the start and length of every value, to use in the SUBSTRING function.
-- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string.
-- Using the t value we can determine which CHARINDEX to look for.
,l(t,s,l) as (select t,s,isnull(nullif(charindex(case t when 'f' then @tagstart when 's' then @tagend when 'e' then @tagstart end,@str,s),0)-s,4000) from s)
-- Each element of the string is returned in an ordered list along with its t value.
-- Where this t value is 's' this means the value is a tag, so append the start and end identifiers and join to the TagReplacementTable.
-- Where no replacement is found, simply return the part of the Description.
-- Finally, concatenate into one string value.
select (select isnull(r.Replacement,k.Item)
from(select row_number() over(order by s) as ItemNumber
,case when l.t = 's' then '[' else '' end
+ substring(@str,s,l)
+ case when l.t = 's' then ']' else '' end as Item
,t
from l
) k
left join TagReplacementTable r
on(k.Item = r.Tag)
order by k.ItemNumber
for xml path('')
) as NewString
);
然後outer apply
到函數的結果做你所有Description
值替換:
declare @t table (Descr nvarchar(100));
insert into @t values('This is [length] ft. long and [height] ft. high'),('[test] This is [other length] ft. long and [other height] ft. high');
select *
from @t t
outer apply dbo.Tag_Replace(t.Descr,'[',']') r;
輸出:
+--------------------------------------------------------------------+-----------------------------------------+
| Descr | NewString |
+--------------------------------------------------------------------+-----------------------------------------+
| This is [length] ft. long and [height] ft. high | This is 75 ft. long and 20 ft. high |
| [test] This is [other length] ft. long and [other height] ft. high | 999 This is 40 ft. long and 50 ft. high |
+--------------------------------------------------------------------+-----------------------------------------+
This一個看起來很緊湊。但有一件事,如果你有超過100個可用的記錄可以替換,你會得到一個錯誤'語句終止。在語句完成之前,最大遞歸100已經耗盡。「但是,您可以在查詢結尾處添加'option(maxrecursion 1000)'來修復它。 – Quark