我查了一下:https://www.red-gate.com/simple-talk/sql/t-sql-programming/concatenating-row-values-in-transact-sql/所以,我的查询是:
SELECT DISTINCT ID, NAME, DOCTEXT2
FROM DOC
CROSS APPLY (SELECT
Stuff((SELECT ' ' + RTRIM(LTRIM(DOCTEXT))
FROM DOC d
WHERE d.ID=DOC.ID AND d.NAME = DOC.NAME
FOR XML PATH (''), TYPE).value('.','varchar(max)'),1,1,'')
) D (DOCTEXT2)
错误是:
FOR XML无法序列化节点'NoName'的数据,因为它包含XML中不允许的字符(0x001E)。要使用FOR XML检索此数据,请将其转换为二进制,varbinary或图像数据类型,并使用BINARY BASE64指令。
我知道我的数据中有0x001E个字符。我不想在数据库中替换这些数据。
我的数据是:
ID NAME DOCTEXT
12 AB ERROR INSTRUCTIONS
12 CC CRN 70 SS
12 CC DRF 77
12 CC
我想要的是,像:
ID NAME DOCTEXT
12 AB ERROR INSTRUCTIONS
12 CC CRN 70 SS DRF 77
如果数据没有0x001E字符,则查询正在运行。
编辑:
我试过:CAST ( REPLACE( DOCTEXT, char(0), '') AS VARCHAR)
而不是RTRIM(LTRIM(DOCTEXT))
,没有成功。
这是笨重的,但你可以在hexstrings中在VARBINARY(MAX)
和NVARCHAR(MAX)
之间来回转换,以避免任何字符XML在文本中不喜欢的问题:
;WITH D1 AS (
SELECT ID, NAME
FROM DOC
GROUP BY ID, NAME
)
SELECT D1.ID, D1.NAME, DOCTEXT =
LTRIM(CONVERT(NVARCHAR(MAX), CONVERT(VARBINARY(MAX), D.DOCTEXT, 2)))
FROM D1 CROSS APPLY (
SELECT NULLIF(
CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), ' ' + LTRIM(RTRIM(D2.DOCTEXT))), 2),
0x)
FROM DOC D2
WHERE D2.ID = D1.ID AND D2.[NAME] = D1.[NAME]
FOR XML PATH('')
) D(DOCTEXT)
我们不能在这里使用BINARY BASE64
,因为连接两个Base64字符串不会(通常)产生另一个Base64字符串。外部LTRIM()
负责删除初始空间;如果你愿意,可以使用STUFF
来获得更精确的结果,但是因为我们正在修剪内部字符串的空格,所以在这里并不重要。
请注意,还有其他方法可以连接字符串(最着名的是SQL Server 2017中的STRING_AGG
)和链接的文章提及它们。这种方法在性能方面不一定是最好的,但我没有测量过。