如何跨行组合 SQL 中的二进制块?

How to combine binary chunks in SQL across rows?

我们需要在 SQL Server 2014 数据库中连接二进制数据块。我们对此的要求是由于 varbinary(max) 数据在 WAN link 上的缓慢复制,如此处所述 - Slow merge replication over a WAN link - only downloads 所以我们不得不将我们的 varbinary(max) 列减少到更小的宽度。

给定一个 table 和一些虚拟数据:

DECLARE @testTable TABLE
(
    [ItemIdx] int,
    [ChunkIdx] int,
    [BinaryData] varbinary(8000)
)
INSERT INTO @testTable ([ItemIdx], [ChunkIdx], [BinaryData]) VALUES (1, 1, 0x00112233), (1, 3, 0x44556677), (1, 2, 0x8899AABB)
INSERT INTO @testTable ([ItemIdx], [ChunkIdx], [BinaryData]) VALUES (2, 1, 0xFFEEDDCC), (2, 3, 0xBBAA9988), (2, 2, 0x77665544)

我可以编写 T-SQL 来连接对应于单个 ItemIdx 的行的数据:

DECLARE @concatData varbinary(max)
SELECT @concatData = COALESCE(@concatData, 0x) + BinaryData FROM @testTable
WHERE ItemIdx = 1
ORDER BY ChunkIdx

这导致 0x001122338899AABB44556677,单个 ItemIdx 的预期结果。

有什么方法可以巧妙地连接所有 ItemIdx 条目吗? 我想要的结果是这样的:

ItemIdx | Data
1       | 0x001122338899AABB44556677
2       | 0xFFEEDDCC77665544BBAA9988

CLR 将是一个非常明智的选择,尽管缺乏对 table 值参数的支持使得我能想到的任何方法都很尴尬。我尝试过使用 GROUP BY、COALESCE、FOR XML、CTE 和其他一些方法,但没有成功。

您可以使用 FOR XML:

加入
DECLARE @ItemIdx INT = 1;

SELECT CONVERT(VARBINARY(MAX),
    (
     SELECT CONVERT(VARCHAR(MAX), BinaryData,2) AS [text()]
     FROM @testTable
     WHERE ItemIdx = @ItemIdx
     ORDER BY ChunkIdx
     FOR XML Path('')
    ),2)

LiveDemo


对于所有行,您可以使用:

SELECT DISTINCT ItemIdx, CONVERT(VARBINARY(MAX),
       (
         SELECT CONVERT(VARCHAR(MAX), BinaryData,2) AS [text()]
         FROM @testTable t2
         WHERE t1.ItemIdx = t2.ItemIdx
         ORDER BY ChunkIdx
         FOR XML Path('')
       ),2) AS Data
FROM @testTable t1;

LiveDemo2

并在 varchar 表格中进行最终检查:

LiveDemo3

输出:

╔═════════╦════════════════════════════╗
║ ItemIdx ║            Data            ║
╠═════════╬════════════════════════════╣
║       1 ║ 0x001122338899AABB44556677 ║
║       2 ║ 0xFFEEDDCC77665544BBAA9988 ║
╚═════════╩════════════════════════════╝