Gunakan pernyataan LIKE di SQL Server XML Datatype

89

Jika Anda memiliki bidang varchar yang dapat Anda lakukan dengan mudah SELECT * FROM TABLE WHERE ColumnA LIKE '%Test%'untuk melihat apakah kolom itu berisi string tertentu.

Bagaimana Anda melakukannya untuk Jenis XML?

Saya memiliki yang berikut ini yang hanya mengembalikan baris yang memiliki simpul 'Teks' tetapi saya perlu mencari di dalam simpul itu

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

Jawaban:

70

Anda seharusnya dapat melakukannya dengan mudah:

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

The .valueMetode memberi Anda nilai aktual, dan Anda dapat menentukan bahwa harus dikembalikan sebagai VARCHAR (), yang kemudian dapat memeriksa dengan laporan SEPERTI.

Pikiran Anda, ini tidak akan terlalu cepat. Jadi jika Anda memiliki bidang tertentu dalam XML yang perlu banyak diperiksa, Anda dapat:

  • buat fungsi tersimpan yang mendapatkan XML dan mengembalikan nilai yang Anda cari sebagai VARCHAR ()
  • tentukan kolom komputasi baru di tabel Anda yang memanggil fungsi ini, dan menjadikannya kolom PERSISTED

Dengan ini, pada dasarnya Anda akan "mengekstrak" bagian tertentu dari XML ke dalam bidang yang dihitung, membuatnya bertahan, dan kemudian Anda dapat mencarinya dengan sangat efisien (heck: Anda bahkan dapat mengindeks bidang itu!).

Marc

marc_s
sumber
1
Saya pada dasarnya menerapkan fitur pencarian, jadi saya ingin mencari kolom XML hanya pada node 'Teks' dan kemudian mengembalikan substring untuk menunjukkan bahwa pencarian telah menemukan kecocokan. Misalnya mencari di 'hai di sana' alih-alih mengembalikan seluruh kolom xml, saya hanya akan mengembalikan substring seperti 'orang itu berkata hai di sana dan dibawa ...'
Jon
1
Pukul saya dengan 5 detik. Kemungkinan lain adalah mempertimbangkan untuk menggunakan pencarian teks gratis, jika data Anda dapat diterima ...
RickNZ
10
untuk mencari seluruh file: WHERE xmlField.value ('.', 'varchar (max)') LIKE '% FOO%'
jhilden
hati-hati dengan namespace Xml yang mengganggu jika Anda mendapatkan NULL kembali
Simon_Weaver
89

Namun opsi lainnya adalah mentransmisikan XML sebagai nvarchar, lalu mencari string yang diberikan seolah-olah XML merupakan bidang nvarchar.

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

Saya menyukai solusi ini karena bersih, mudah diingat, sulit untuk dikacaukan, dan dapat digunakan sebagai bagian dari klausa where.

EDIT: Seperti yang dikatakan Cliff, Anda dapat menggunakan:

... nvarchar jika ada karakter yang tidak dikonversi ke varchar

Squazz
sumber
3
Ditto itu, atau nvarchar jika ada karakter yang tidak dikonversi ke varchar SELECT * FROM Table WHERE CAST (Column as nvarchar (max)) LIKE '% TEST%'
Cliff Coulter
[Err] 42000 - [SQL Server] Konversi satu atau lebih karakter dari XML ke pemeriksaan target tidak mungkin
digz6666
[Err] 22018 - [SQL Server] Konversi eksplisit dari tipe data xml ke teks tidak diperbolehkan.
digz6666
Sepertinya Anda melakukan sesuatu yang salah @ digz6666
Squazz
1
@Squazz Anda terakhir memberikan suara untuk jawaban ini kemarin. Pilihan Anda sekarang terkunci kecuali jawaban ini diedit. :)
digz6666
10

Pilihan lainnya adalah mencari XML sebagai string dengan mengubahnya menjadi string dan kemudian menggunakan LIKE. Namun karena kolom yang dihitung tidak bisa menjadi bagian dari klausa WHERE Anda perlu membungkusnya di SELECT lain seperti ini:

SELECT * FROM
    (SELECT *, CONVERT(varchar(MAX), [COLUMNA]) as [XMLDataString] FROM TABLE) x
WHERE [XMLDataString] like '%Test%'
Carl Onager
sumber
Harap diperhatikan bahwa ini dapat melewati indeks xml selektif apa pun yang mungkin Anda miliki dan berdampak buruk pada kinerja.
Rudy Hinojosa
0

Inilah yang akan saya gunakan berdasarkan jawaban 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

Kembalikan substring pada pencarian di mana terdapat kriteria pencarian

Jon
sumber
Apakah saya memerlukan parameter untuk mencegah injeksi?
Jon
2
WASPADA: fungsi XML tersebut Peka huruf besar / kecil - DATA.VALUE tidak akan berfungsi! Perlu .value (...)
marc_s