视图的嵌套查询中的计算列

时间:2012-07-20 11:56:37

标签: sql sql-server xml sql-server-2008

我有一个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

这会产生:

  

Msg 9400,Level 16,State 1,Line 1 XML解析:第1行,第5个字符,   意外的输入结束

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

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

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

P.S。 Microsoft SQL Server 2008(SP3) - 10.0.5500.0(X64)2011年9月21日22:45:45版权所有(c)1988-2008 Windows NT 6.1上的Microsoft Corporation Express Edition(64位)(Build 7601:Service Pack 1)

1 个答案:

答案 0 :(得分:1)

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

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

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

您可能对SQL Server: inline conditional convert with XML?In SQL Server, what is the best way to determine if a given string is a valid XML or not?感兴趣。

似乎没有一种简单的方法可以做你想要的。但是,您可以对原始字符串进行简单检查,看看它是否合理。例如,以下检查是否有相同数量的“&lt;”和“&gt;”:

select (case when len(replace(val, '<', '')) = len(replace(val, '>', ''))
             then 'MAYBE OKAY'
             else 'NOPE'
        end)
from (select '<badness' as val) t