FOR XML PATH不适用于0x001E字符

问题描述 投票:0回答:1

我查了一下: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)),没有成功。

sql-server tsql for-xml-path
1个回答
1
投票

这是笨重的,但你可以在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)和链接的文章提及它们。这种方法在性能方面不一定是最好的,但我没有测量过。

© www.soinside.com 2019 - 2024. All rights reserved.