Вы можете сделать это, разбив исходный текст на составные слова, используя функцию разделения строк, а затем join
вставив, где требуется, в ваш base64Table
, чтобы получить соответствующие значения замены, а затем рекомбинируя с помощью либо FOR XML
, либоSTRING_AGG
в зависимости от того, используется ли ваш SQL Server до или после 2017 года.
Если вы используете SQL Server 2016 или выше, вы также можете использовать STRING_SPLIT
, а если нет, то можете использовать функцию в конце этогоответ, который является моей модифицированной версией Джеффа Модена .
declare @b table(id int,p varchar(100));
insert into @b values(1,'THIS IS PICTURE 1'),(2,'THIS IS PICTURE 2'),(3,'THIS IS PICTURE 3');
declare @t table(v varchar(500));
insert into @t values('A picture is right here <##1##> and then here is some text and another picture <##2##> and here is the end'),('Another picture is here <##1##> and yet more text and another picture <##2##> and here is the end');
select t.v as Original
,stuff((select ' ' + isnull(b.p,s.Item)
from dbo.fn_StringSplit4k(t.v,' ',null) as s
left join @b as b
on left(s.Item,3) = '<##'
and cast(substring(s.Item,4,1) as int) = b.id
order by s.rn
for xml path('')
),1,1,'') as Replaced
from @t as t;
Вывод
+------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+
| Original | Replaced |
+------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+
| A picture is right here <##1##> and then here is some text and another picture <##2##> and here is the end | A picture is right here THIS IS PICTURE 1 and then here is some text and another picture THIS IS PICTURE 2 and here is the end |
| Another picture is here <##1##> and yet more text and another picture <##2##> and here is the end | Another picture is here THIS IS PICTURE 1 and yet more text and another picture THIS IS PICTURE 2 and here is the end |
+------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+
Сверните свой собственный String Split
create function dbo.fn_StringSplit4k
(
@str nvarchar(4000) = ' ' -- String to split.
,@delimiter as nvarchar(1) = ',' -- Delimiting value to split on.
,@num as int = null -- Which value to return.
)
returns table
as
return
-- Start tally table with 10 rows.
with n(n) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)
-- 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(isnull(@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 follows the specified delimiter.
,s(s) as (select 1 union all select t+1 from t where substring(isnull(@str,''),t,1) = @delimiter)
-- 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.
,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,isnull(@str,''),s),0)-s,4000) from s)
select rn
,item
from(select row_number() over(order by s) as rn
,substring(@str,s,l) as item
from l
) a
where rn = @num
or @num is null;
Снова глядя на ваш вопрос, вам может понадобиться разделитель строк, который может обрабатывать более 4000 символов.Если это так, вы можете использовать это вместо этого, хотя он может работать хуже на меньших строках, чем версия 4k:
create function dbo.fn_StringSplitMax
(
@str nvarchar(max) = ' ' -- String to split.
,@delimiter as nvarchar(max) = ',' -- Delimiting value to split on.
,@num as int = null -- Which value to return.
)
returns table
as
return
with s as
( -- Convert the string to an XML value, replacing the delimiter with XML tags
select convert(xml,'<x>' + replace((select @str for xml path('')),@delimiter,'</x><x>') + '</x>').query('.') as s
)
select rn
,item -- Select the values from the generated XML value by CROSS APPLYing to the XML nodes
from(select row_number() over (order by (select null)) as rn
,n.x.value('.','nvarchar(max)') as item
from s
cross apply s.nodes('x') as n(x)
) a
where rn = @num
or @num is null;