FOR XML PATH 不适用于 0x001E 字符

FOR XML PATH doesn't work with 0x001E character

我检查过: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 could not serialize the data for node 'NoName' because it contains a character (0x001E) which is not allowed in XML. To retrieve this data using FOR XML, convert it to binary, varbinary or image data type and use the BINARY BASE64 directive.

我知道数据中有 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)),没有成功。

它很笨重,但您可以在十六进制字符串中的 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() 负责删除初始的 space;如果您愿意,可以使用 STUFF 来获得更精确的结果,但由于我们正在修剪内部字符串的 space,所以这里并不重要。

请注意,还有其他连接字符串的方法(最著名的是 SQL Server 2017 中的 STRING_AGG),您链接到的文章中提到了它们。这种方法在性能方面不一定是最好的,但我没有测量过。