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)2011年9月21日22:45:45 Copyright(c)1988-2008 Microsoft Corporation Express Edition(64-bit)on 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: inline conditional convert with 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 に答える