2

我们正在尝试用单个查询连接 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 字符。

提前致谢。

4

4 回答 4

2

正如@Martin 的评论中所建议的那样,我会考虑使用 CLR 集成。CLR 聚合函数可能只是票证。

于 2011-05-11T16:17:44.183 回答
1

究竟是什么填满了 tempdb?不可能@concatText = @concatText + [ColumnText],不涉及不变性,@concatText 变量在最坏的情况下将是 2GB 大小(我希望你的 tempdb 比这大得多,如果不增加它)。看起来您的查询计划更像是为 haloween 保护创建了一个假脱机,而该假脱机是罪魁祸首。

作为一个通用答案,UPDATE ... SET @var = @var + ...已知使用 for 连接存在正确性问题并且不受支持。在 Transact-SQL中连接行值中讨论了更可靠的替代方法。

于 2011-05-11T18:33:55.777 回答
0

首先,从您的帖子中,尚不清楚您是否需要或为什么需要临时表。连接可以在查询中内联完成。如果您向我们展示有关填充 tempdb 的查询的更多信息,我们也许可以帮助您重写它。其次,没有提到的一个选项是完全在 T-SQL 之外进行字符串操作。即,在您对原始数据的中间层查询中,进行操作并将其推回数据库。最后,您可以使用 Xml 以便结果正确处理转义和实体。同样,我们需要更多地了解您要完成的工作和方式。

于 2011-05-11T16:52:21.030 回答
0

Agreed..A CLR User Defined Function would be the best approach for what you guys are doing. You could actually read the text values into an object and then join them all together (inside the CLR) and have the function spit out a NVARCHAR(MAX) result. If you need details on how to do this let me know.

于 2011-05-12T01:28:46.613 回答