Sql server 如何正确替换一行中多次使用的预定义分隔符
我有一个保存纯文本的列,并使用分隔符将第一个表中base64中的图像替换为由几个唯一字符和base64表ID组成的分隔符 例如: 表 备注栏 一张图片就在这里,然后是一些文本和另一张图片,这是结尾 每个实例可以返回多个结果。带有1个分隔符的行可以正常工作。这里的问题是,当我尝试根据整个页面选择要显示的具有多个分隔符的分隔符时,它将显示类似这样的内容,其中显示为多行 这里有一张图片数据:image/png;base64。。。这是一些文字和另一张图片,这是结尾 图片就在这里,然后是一些文本和另一个图片数据:image/png;base64。。。结束了 我的一般疑问是Sql server 如何正确替换一行中多次使用的预定义分隔符,sql-server,tsql,Sql Server,Tsql,我有一个保存纯文本的列,并使用分隔符将第一个表中base64中的图像替换为由几个唯一字符和base64表ID组成的分隔符 例如: 表 备注栏 一张图片就在这里,然后是一些文本和另一张图片,这是结尾 每个实例可以返回多个结果。带有1个分隔符的行可以正常工作。这里的问题是,当我尝试根据整个页面选择要显示的具有多个分隔符的分隔符时,它将显示类似这样的内容,其中显示为多行 这里有一张图片数据:image/png;base64。。。这是一些文字和另一张图片,这是结尾 图片就在这里,然后是一些文本和另一个图
SELECT REPLACE(A.notesColumn,'<##'+CAST(B.base64ID AS VARCHAR(25))+'##>', B.docImage) [noteText]
FROM tableA A
LEFT JOIN base64Table B ON A.ID = B.tableANote
WHERE pageID = @pageID
如何解决显示为多个结果而仅显示一行的问题,无论有多少分隔符?您都可以通过使用字符串拆分函数将原始文本拆分为组成词,然后在需要时将其加入Base64表以获取相关的替换值,然后根据SQL Server是pre还是pre,通过FOR XML或string_AGG进行重新组合2017年后 如果您使用的是SQL Server 2016或更高版本,您也可以使用STRING_SPLIT,如果不是,您可以使用此答案末尾的函数,这是我的修改版 再看看您的问题,您可能需要一个可以处理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;
这是一个罕见的时刻,一个古怪的更新可以帮助很多: @iamdave的信用卡,使用了部分mcve
CREATE TABLE B(id int,p varchar(100));
insert into B values(1,'THIS IS PICTURE 1'),(2,'THIS IS PICTURE 2'),(3,'THIS IS PICTURE 3');
GO
CREATE TABLE A(v varchar(500));
insert into A 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')
,('Another example with a picutre <##2##> here and one more here <##3##>');
GO
-清理:小心真实数据
DROP FUNCTION dbo.MultipleImageReplace;
GO
DROP TABLE B;
GO
DROP TABLE A;
DROP TABLE B;
GO
DROP TABLE A;
结果
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 THIS IS PICTURE 1 and yet more text and another picture THIS IS PICTURE 2 and here is the end
Another example with a picutre THIS IS PICTURE 2 here and one more here THIS IS PICTURE 3
神奇古怪更新的一些背景:
该函数使用@input=Modify@input. 这将导致一个逐行操作,表B的每一行都将修改@input的内容并将其重新分配给变量。因此,下一行将处理修改后的内容,依此类推
这种方法有一些严重的缺点,一般不推荐使用。但在这种情况下,排序并不重要,你可以试一试。我将此作为第二个答案,因为方法与另一个完全不同,我不想混淆这一点 您可以使用XQuery及其强大的功能来处理通用数据 测试场景:
CREATE TABLE B(id int,p varchar(100));
insert into B values(1,'THIS IS PICTURE 1'),(2,'THIS IS PICTURE 2'),(3,'THIS IS PICTURE 3');
GO
CREATE TABLE A(v varchar(500));
insert into A 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')
,('Another example with a picutre <##2##> here and one more here <##3##>');
GO
一个经过转换的XML如下所示:
<root>
<row>
<text>Another example with a picutre </text>
<img index="2" />
<text> here and one more here </text>
<img index="3" />
<text />
</row>
<images>
<img>
<id>1</id>
<p>THIS IS PICTURE 1</p>
</img>
<img>
<id>2</id>
<p>THIS IS PICTURE 2</p>
</img>
<img>
<id>3</id>
<p>THIS IS PICTURE 3</p>
</img>
</images>
</root>
是一个很好的起点。请与我们共享tableB的内容。@donPablo如果您引用的是Base64表,则内容为ID、tableAID FK、docImage VARCHARMAXNo,仅列出列是无用的。没有人能对此提出质疑。我们需要基于您的示例数据获得表定义、示例数据和所需输出。我怀疑这可以通过使用Quirk更新来实现,但没有进一步的信息,我无法确认。您的函数fn_StringSplit4k在哪里?
DROP FUNCTION dbo.MultipleImageReplace;
GO
DROP TABLE B;
GO
DROP TABLE A;
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 THIS IS PICTURE 1 and yet more text and another picture THIS IS PICTURE 2 and here is the end
Another example with a picutre THIS IS PICTURE 2 here and one more here THIS IS PICTURE 3
CREATE TABLE B(id int,p varchar(100));
insert into B values(1,'THIS IS PICTURE 1'),(2,'THIS IS PICTURE 2'),(3,'THIS IS PICTURE 3');
GO
CREATE TABLE A(v varchar(500));
insert into A 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')
,('Another example with a picutre <##2##> here and one more here <##3##>');
GO
WITH Casted AS
(
SELECT *
,CAST('<root>
<row>
<text>' + REPLACE(REPLACE(A.v,'<##','</text><img index="'),'##>','"/><text>') + '</text>
</row>
<images>' +
--and we will include the pictures to be part of the XML
--this will make it easier to use them in the XQuery
--You might use two CTEs to include just the pictures needed
(
SELECT *
FROM B
FOR XML PATH('img')
) +
'</images>
</root>
' AS XML) AS CastedToXml
FROM A
)
--We use a simple "for .. in .." loop to travers down the nodes and return their content "as-is" or replaced by the corresponding image
SELECT CastedToXml.query('for $nd in /root/row/*
return
if(local-name($nd)="img") then
/root/images/img[id=$nd/@index]/p/text()
else
$nd/text()
').value('.','nvarchar(max)')
FROM Casted
GO
DROP TABLE B;
GO
DROP TABLE A;
<root>
<row>
<text>Another example with a picutre </text>
<img index="2" />
<text> here and one more here </text>
<img index="3" />
<text />
</row>
<images>
<img>
<id>1</id>
<p>THIS IS PICTURE 1</p>
</img>
<img>
<id>2</id>
<p>THIS IS PICTURE 2</p>
</img>
<img>
<id>3</id>
<p>THIS IS PICTURE 3</p>
</img>
</images>
</root>
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 THIS IS PICTURE 1 and yet more text and another picture THIS IS PICTURE 2 and here is the end
Another example with a picutre THIS IS PICTURE 2 here and one more here THIS IS PICTURE 3