Sql server FOR XML无法序列化节点的数据,因为它包含XML中不允许的字符(0x0001)

Sql server FOR XML无法序列化节点的数据,因为它包含XML中不允许的字符(0x0001),sql-server,tsql,Sql Server,Tsql,我第一次尝试在SQLServer2008上的T-SQL中使用XML。对于我的大表中的一列,我收到以下错误消息: FOR XML could not serialize the data for node because it contains a character (0x0001) which is not allowed in XML. To retrieve this data using FOR XML, convert it to binary, varbinary or image

我第一次尝试在SQLServer2008上的T-SQL中使用XML。对于我的大表中的一列,我收到以下错误消息:

FOR XML could not serialize the data for node because it contains a character (0x0001) 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.
我猜了一下,试了一下:

select * from db.dbo.table where colThatGeneratedError like '%0x0001%'
但它没有引起争论

如何找出表中的哪一行包含无效字符

0x0001指的是什么字符?在我看来,这看起来像是1的十六进制=十进制1

 select * from db.dbo.table where (PATINDEX('%[A,Z,0-9]%[A,Z,0-9]%[A,Z,0-9]%',colThatGeneratedError) >0) 

在TSQL中,您可以使用CHAR函数,例如

select * from db.dbo.table where CHARINDEX(CHAR(1), colThatGeneratedError) <> 0
从db.dbo.table中选择*其中CHARINDEX(CHAR(1),colthatGenerateError)0
它对我有用。很可能是excel中的特殊输入。

select*
select *
FROM (SELECT a = '<'+nchar(2)+'>') x
for xml path(''),type
从(选择a=“”)x 对于xml路径(“”),键入
对于上面的statemnet,您将得到此错误

FOR XML无法序列化节点“a”的数据,因为它包含 XML中不允许的字符(0x0002)。要检索此 用于XML的数据,将其转换为二进制、varbinary或图像数据类型 并使用BINARY BASE64指令

我创建了一个sql函数来解决这个问题

USE master;
GO
IF (OBJECT_ID('str_to_xml') IS NOT NULL) DROP FUNCTION dbo.str_to_xml;
GO
CREATE FUNCTION dbo.str_to_xml(@input AS nvarchar(max))
RETURNS xml
BEGIN
    DECLARE @i int, @iText nvarchar(100);
    SET @i = 0x0;
    WHILE (@i <= 0x8)
    WHILE (@i <= 0xFFFF)
    BEGIN
        SET @iText = master.dbo.fn_varbintohexstr(@i);
        SET @iText = ISNULL(STUFF(@iText, 1, PATINDEX('%[^0x]%', @iText) - 1, ''), '0');
        SET @iText = '&#x' + CASE WHEN LEN(@iText) > 1 THEN '' ELSE '0' END + @iText + ';';
        SET @input = REPLACE(@input, @iText, '');
        SET @i = CASE
            WHEN @i + 1 BETWEEN 0x9 AND 0xA THEN 0xA
            WHEN @i + 1 = 0xD THEN 0xD
            WHEN @i + 1 BETWEEN 0x20 AND 0xD7FF THEN 0xD7FF
            WHEN @i + 1 BETWEEN 0xE000 AND 0xFFFD THEN 0xFFFD
            ELSE @i + 1 END + 1;
    END
    RETURN CONVERT(xml, @input);
END
GO
使用master;
去
如果(OBJECT_ID('str_to_xml')不为空,则将函数dbo.str_to_xml;
去
创建函数dbo.str_to_xml(@input AS nvarchar(max))
返回xml
开始
声明@i int,@iText nvarchar(100);
设置@i=0x0;

虽然(@i Try
'%\u0001%'
。不确定。你可以先尝试
\u0030
,数字“0”。哇。它可以工作,但效率不高。你对这些范围内的每个字符进行替换,大约有2000个不同的字符。另外,我注意到一个错误。你大部分时间都会增加2,而不是1。应该是:ELSE@i END+1;你需要什么应该做的是将字符串转换为字符数组,然后检查每个字符是否处于“坏范围”。您可能也可以不使用while循环来执行此操作。但更好的是,删除“for XML”之后的“TYPE”没有错误。我猜是因为结果是字符串而不是XML数据类型。另外,您有两个while语句。我认为“while(@I
USE master;
GO
IF (OBJECT_ID('str_to_xml') IS NOT NULL) DROP FUNCTION dbo.str_to_xml;
GO
CREATE FUNCTION dbo.str_to_xml(@input AS nvarchar(max))
RETURNS xml
BEGIN
    DECLARE @i int, @iText nvarchar(100);
    SET @i = 0x0;
    WHILE (@i <= 0x8)
    WHILE (@i <= 0xFFFF)
    BEGIN
        SET @iText = master.dbo.fn_varbintohexstr(@i);
        SET @iText = ISNULL(STUFF(@iText, 1, PATINDEX('%[^0x]%', @iText) - 1, ''), '0');
        SET @iText = '&#x' + CASE WHEN LEN(@iText) > 1 THEN '' ELSE '0' END + @iText + ';';
        SET @input = REPLACE(@input, @iText, '');
        SET @i = CASE
            WHEN @i + 1 BETWEEN 0x9 AND 0xA THEN 0xA
            WHEN @i + 1 = 0xD THEN 0xD
            WHEN @i + 1 BETWEEN 0x20 AND 0xD7FF THEN 0xD7FF
            WHEN @i + 1 BETWEEN 0xE000 AND 0xFFFD THEN 0xFFFD
            ELSE @i + 1 END + 1;
    END
    RETURN CONVERT(xml, @input);
END
GO
select master.dbo.str_to_xml((select *
FROM (SELECT a = '<'+nchar(2)+'>') x
for xml path('')))