我们试图用一个查询连接SQL中可能有数千行文本。我们目前的查询如下所示:
DECLARE @concatText NVARCHAR(MAX)
SET @concatText = ''
UPDATE TOP (SELECT MAX(PageNumber) + 1 FROM #OrderedPages) [#OrderedPages]
SET @concatText = @concatText + [ColumnText] + '
'
WHERE (RTRIM(LTRIM([ColumnText])) != '')
从功能的角度来看,这是完美的。我们唯一的问题是有时ColumnText的长度可能只有几千字节。结果,当我们有数千行时,我们正在填充tempDB。
我们提出的最好的理由是,当我们对@concatText进行这些更新时,SQL正在使用隐式事务,因此字符串实际上是不可变的。
我们正试图找出解决这个问题的好方法,到目前为止我们有两种可能的解决方案: 1)在.NET中进行连接。这是一个可以选择的选项,但这可能会回到网上。
2)使用.WRITE,其操作方式与.NET的String.Join方法类似。我无法弄清楚这个的语法,因为BoL没有涵盖这个级别的SQL恶作剧。
这引出了一个问题:.WRITE会起作用吗?如果是这样,语法是什么?如果没有,有没有其他方法可以做到这一点,而无需向.NET发送数据?我们无法使用FOR XML
,因为我们的文字可能包含非法的XML字符。
提前致谢。
答案 0 :(得分:2)
我正在考虑使用CLR集成,正如@ Martin的评论中所建议的那样。 CLR聚合函数可能就是故障单。
答案 1 :(得分:1)
究竟是什么填补了tempdb?它不能是@concatText = @concatText + [ColumnText]
,不存在不变性,而@concatText变量在最坏的情况下是2GB大小(我希望你的tempdb远大于它,如果没有增加它)。看起来更像是你的查询计划为haloween保护创建一个假脱机,而假脱机是罪魁祸首。
作为一般答案,使用UPDATE ... SET @var = @var + ...
进行连接已知具有正确性问题,并且不受支持。 Concatenating Row Values in Transact-SQL中讨论了更可靠的替代方法。
答案 2 :(得分:0)
首先,从您的帖子中,不清楚您是否需要临时表或为什么需要临时表。连接可以在查询中内联完成。如果您向我们展示了有关填充tempdb的查询的更多信息,我们可能会帮助您重写它。其次,没有提到的选项是完全在T-SQL之外进行字符串操作。即,在对原始数据的中间层查询中,执行操作并将其推回到数据库。最后,您可以使用Xml,以便结果正确处理转义和实体。同样,我们需要更多地了解您想要实现的目标和方式。
答案 3 :(得分:0)
同意..一个CLR用户定义函数将是你们正在做的最好的方法。您实际上可以将文本值读入一个对象,然后将它们连接在一起(在CLR内)并让函数吐出一个NVARCHAR(MAX)结果。如果您需要有关如何执行此操作的详细信息,请与我们联系。