1

我有一个表,其中的nvarchar(max)列可能包含已知结构的 xml。我想解析它以执行一些聚合,因此需要过滤掉“坏”条目。这是测试用例:

create table TestTable ([Message] nvarchar(max))
insert into TestTable ([Message]) values 
    ('<root m="1"/>'),
    ('<root m="7"/>'),
    ('<rooo')
go

set quoted_identifier on
go   

create view TestView as
select data.value('(/root/@m)[1]', 'int') as MyValue
from (
    select cast([Message] as xml) as data
    from (
        select [Message] from dbo.TestTable where [Message] like '<root%>'
    ) as T1
) as T2
where data.exist('/root') = 1
go

select * from TestView

这会产生:

消息 9400,级别 16,状态 1,第 1 行 XML 解析:第 1 行,字符 5,输入意外结束

我不明白为什么,因为如果我运行嵌套查询:

    select cast([Message] as xml) as data
    from (
        select [Message] from dbo.TestTable where [Message] like '<root%>'
    ) as T1

它完美地返回 2 个有效行。为什么??

ps Microsoft SQL Server 2008 (SP3) - 10.0.5500.0 (X64) Sep 21 2011 22:45:45 版权所有 (c) 1988-2008 Microsoft Corporation Express Edition (64-bit) o​​n Windows NT 6.1 (Build 7601: Service Pack 1 )

4

1 回答 1

1

您的问题不在 select 子句中,而是在 where 子句中:

where data.exist('/root') = 1

我怀疑你在想:“啊哈!如果 xml 格式不正确,那么这将返回 0 或 NULL”。不,这个函数——与其他 xml 函数一样——需要有效的 xml。或者它得到一个错误。

您可能对SQL Server 感兴趣:使用 XML 进行内联条件转换?在 SQL Server 中,确定给定字符串是否为有效 XML 的最佳方法是什么?.

似乎没有一种简单的方法可以做你想做的事。但是,您也许可以对原始字符串进行简单检查,看看它是否是合理的 xml。例如,以下检查是否存在相同数量的“<”和“>”:

select (case when len(replace(val, '<', '')) = len(replace(val, '>', ''))
             then 'MAYBE OKAY'
             else 'NOPE'
        end)
from (select '<badness' as val) t
于 2012-07-20T14:00:36.627 回答