FOR XML无法序列化节点NoName的数据-无法替换XML字符

时间:2018-12-04 03:29:32

标签: sql sql-server xml

我正在使用SQL Server 2014,正在尝试从表中的数据中删除XML字符,并且大多数XML字符都可以成功使用。但是我对此字符有疑问:0xDE7B

我有一个包含STUFF函数的T-SQL语句:

SELECT DISTINCT
    b.[Doc#],
    STUFF((SELECT '; ' + ltrim(rtrim(a.[MyColumn]))
           FROM #temp th
           WHERE a.[Doc#] = b.[Doc#]
           GROUP BY ltrim(rtrim(a.[MyColumn]))
           FOR XML PATH (''), TYPE).value('(./text())[1]', 'varchar(max)'), 1, 2, '') [MyColumn]

我收到以下错误:

  

6841,第16级,状态1,第547行
  FOR XML无法序列化节点'NoName'的数据,因为它包含XML不允许的字符(0xDE7B)。要使用FOR XML检索此数据,请将其转换为二进制,varbinary或图像数据类型,然后使用BINARY BASE64指令。

但是当我执行以下操作时:

REPLACE([MyColumn], CHAR(0xDE7B), '')

这最终使该列中的所有值都为NULL。我有一个删除所有其他XML字符(即0x0000、0x0001、0x0002 ...)的函数,它似乎适用于它们。

1 个答案:

答案 0 :(得分:0)

有问题的字符是

您不应尝试使用自己的替换逻辑来摆脱禁止的字符。有很多可能的候选人。即使这行得通,明天您可能会得到一个新的,您没有考虑过……XML正在为您暗中这么做。试试这个:

SELECT (SELECT 'This inlcudes forbidden characters like < & > and your �' AS [*] FOR XML PATH(''));

结果将为“ This inlcudes forbidden characters like &lt; &amp; &gt; and your ?

引擎显然使用了一个简单的问号而不是``。为什么...

您可以像这样在代码中使用它

SELECT DISTINCT
    b.[Doc#],
    STUFF((SELECT '; ' + ltrim(rtrim((SELECT a.[MyColumn] AS [*] FOR XML Path('')))) --<-- a.MyColumn should be NVARCHAR(X)
           FROM #temp th
           WHERE a.[Doc#] = b.[Doc#]
           GROUP BY ltrim(rtrim((SELECT a.[MyColumn] AS [*] FOR XML Path(''))))
           FOR XML PATH (''), TYPE).value('(./text())[1]', 'nvarchar(max)'), 1, 2, '') [MyColumn]

确保不要让任何VARCHAR干扰。所有涉及的列和所有涉及的步骤(函数(!))必须接受NVARCHAR并返回NVARCHAR

因此,我也将您的最终.value()的返回类型也更改为nvarchar(max)