SQL ServerXMLデータ型でLIKEステートメントを使用する


86

varcharフィールドがある場合SELECT * FROM TABLE WHERE ColumnA LIKE '%Test%'は、その列に特定の文字列が含まれているかどうかを簡単に確認できます。

XMLタイプに対してどのようにそれを行いますか?

'Text'ノードを持つ行のみを返す次のものがありますが、そのノード内を検索する必要があります

select * from WebPageContent where data.exist('/PageContent/Text') = 1

回答:


70

これは非常に簡単に実行できるはずです。

SELECT * 
FROM WebPageContent 
WHERE data.value('(/PageContent/Text)[1]', 'varchar(100)') LIKE 'XYZ%'

この.valueメソッドは実際の値を提供し、それをVARCHAR()として返すように定義できます。これは、LIKEステートメントで確認できます。

気をつけてください、これはひどく速くなることはないでしょう。したがって、XMLに多くの検査が必要な特定のフィールドがある場合は、次のことができます。

  • XMLを取得し、探している値をVARCHAR()として返すストアド関数を作成します
  • この関数を呼び出す新しい計算フィールドをテーブルに定義し、それをPERSISTED列にします

これにより、基本的にXMLの特定の部分を計算フィールドに「抽出」し、それを永続化して、非常に効率的に検索できます(つまり、そのフィールドにインデックスを付けることもできます)。

マーク


1
私は基本的に検索機能を実装しているので、「テキスト」ノードでのみXML列を検索し、検索で一致が見つかったことを示す部分文字列を返します。「やあ」の代わりに全体のxml列を返すので、私はちょうどサブストリングこのような「やつはこんにちは言ったと運ば...」と返すと思います上の例の検索のための
ジョン

1
5秒で私を殴りました。別の可能性は、データが受け入れられる場合は、フリーテキスト検索の使用を検討することです...
RickNZ 2009

10
ファイル全体を検索するには:WHERE xmlField.value( '。'、 'varchar(max)')LIKE '%FOO%'
jhilden 2013

あなたがNULLの取り戻す場合は厄介なXML名前空間に気を付ける
Simon_Weaver

86

さらに別のオプションは、XMLをnvarcharとしてキャストし、XMLがnvarcharフィールドを介しているかのように指定された文字列を検索することです。

SELECT * 
FROM Table
WHERE CAST(Column as nvarchar(max)) LIKE '%TEST%'

このソリューションは、クリーンで覚えやすく、混乱しにくく、where句の一部として使用できるため、気に入っています。

編集:クリフがそれを述べているように、あなたは使うことができます:

... varcharに変換されない文字がある場合はnvarchar


3
同じように、またはvarcharに変換されない文字がある場合はnvarchar SELECT * FROM Table WHERE CAST(Column as nvarchar(max))LIKE '%TEST%'
Cliff Coulter 2017年

[エラー]
42000- [SQLServer

[エラー] 22018- [SQLServer]データ型xmlからテキストへの明示的な変換は許可されていません。
digz6666 2017年

何か間違ったことをしているようですね@ digz6666
Squazz

1
@Squazz昨日この回答に最後に投票しました。この回答が編集されない限り、投票はロックインされます。:)
digz6666 2017年

10

もう1つのオプションは、XMLを文字列に変換してから、LIKEを使用して、XMLを文字列として検索することです。ただし、計算列をWHERE句の一部にすることはできないため、次のように別のSELECTでラップする必要があります。

SELECT * FROM
    (SELECT *, CONVERT(varchar(MAX), [COLUMNA]) as [XMLDataString] FROM TABLE) x
WHERE [XMLDataString] like '%Test%'

これにより、選択したxmlインデックスがバイパスされ、パフォーマンスが低下する可能性があることに注意してください。
RudyHinojosa19年

0

これは、marc_sの回答に基づいて使用するものです。

SELECT 
SUBSTRING(DATA.value('(/PAGECONTENT/TEXT)[1]', 'VARCHAR(100)'),PATINDEX('%NORTH%',DATA.value('(/PAGECONTENT/TEXT)[1]', 'VARCHAR(100)')) - 20,999)

FROM WEBPAGECONTENT 
WHERE COALESCE(PATINDEX('%NORTH%',DATA.value('(/PAGECONTENT/TEXT)[1]', 'VARCHAR(100)')),0) > 0

検索条件が存在する検索で部分文字列を返します


どういうわけか注射を防ぐためのパラメータが必要ですか?
ジョン

2
注意:これらのXML関数では大文字と小文字が区別されます-DATA.VALUE機能しません
.value
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.