ใช้คำสั่ง LIKE บน SQL Server XML Datatype


89

หากคุณมีฟิลด์ varchar คุณสามารถทำได้อย่างง่ายดายSELECT * FROM TABLE WHERE ColumnA LIKE '%Test%'เพื่อดูว่าคอลัมน์นั้นมีสตริงที่แน่นอนหรือไม่

คุณทำสิ่งนั้นสำหรับประเภท XML ได้อย่างไร?

ฉันมีสิ่งต่อไปนี้ซึ่งส่งคืนเฉพาะแถวที่มีโหนด 'ข้อความ' แต่ฉันต้องการค้นหาภายในโหนดนั้น

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 () ซึ่งคุณสามารถตรวจสอบที่มีคำสั่งเช่น

โปรดทราบว่านี่จะไม่เร็วมาก ดังนั้นหากคุณมีบางช่องใน XML ที่ต้องตรวจสอบจำนวนมากคุณสามารถ:

  • สร้างฟังก์ชันที่เก็บไว้ซึ่งรับ XML และส่งคืนค่าที่คุณต้องการเป็น VARCHAR ()
  • กำหนดเขตข้อมูลที่คำนวณใหม่บนตารางของคุณซึ่งเรียกใช้ฟังก์ชันนี้และทำให้เป็นคอลัมน์ PERSISTED

ด้วยสิ่งนี้โดยพื้นฐานแล้วคุณจะ "แยก" ส่วนหนึ่งของ XML ลงในช่องที่คำนวณแล้วทำให้มันคงอยู่และจากนั้นคุณสามารถค้นหาได้อย่างมีประสิทธิภาพ (ห่า: คุณสามารถ INDEX ฟิลด์นั้นได้ด้วย!)

มาร์ค


1
โดยพื้นฐานแล้วฉันใช้คุณลักษณะการค้นหาดังนั้นฉันจึงต้องการค้นหาคอลัมน์ XML บนโหนด "ข้อความ" เท่านั้นจากนั้นส่งคืนสตริงย่อยเพื่อระบุว่าการค้นหาพบรายการที่ตรงกัน ตัวอย่างเช่นการค้นหาใน 'hi there' แทนที่จะส่งคืนคอลัมน์ xml ทั้งหมดฉันแค่ส่งคืนสตริงย่อยเช่น 'the chap said hi there and carry ... '
Jon

1
เอาชนะฉันไป 5 วินาที ความเป็นไปได้อีกประการหนึ่งคือการพิจารณาใช้การค้นหาข้อความฟรีหากข้อมูลของคุณคล้อยตาม ...
RickNZ

11
เพื่อค้นหาไฟล์ทั้งหมด: WHERE xmlField.value ('.', 'varchar (max)') LIKE '% FOO%'
jhilden

ระวังเนมสเปซ Xml ที่น่ารำคาญหากคุณได้รับ NULL กลับมา
Simon_Weaver

90

อีกทางเลือกหนึ่งคือการส่ง XML เป็น nvarchar จากนั้นค้นหาสตริงที่กำหนดราวกับว่า XML กับฟิลด์ nvarchar

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

ฉันชอบโซลูชันนี้เพราะมันสะอาดจำง่ายไม่เลอะเทอะและสามารถใช้เป็นส่วนหนึ่งของประโยค where ได้

แก้ไข: ตามที่ Cliff กล่าวถึงคุณสามารถใช้:

... nvarchar หากมีอักขระที่ไม่ได้แปลงเป็น varchar


3
ทำเช่นนั้นหรือ nvarchar หากมีอักขระที่ไม่แปลงเป็น varchar SELECT * จากตาราง WHERE CAST (คอลัมน์เป็น nvarchar (สูงสุด)) เช่น '% TEST%'
Cliff Coulter

[Err] 42000 - [SQL Server] การแปลงอักขระตั้งแต่หนึ่งตัวขึ้นไปจาก XML เป็นการจัดเรียงเป้าหมายเป็นไปไม่ได้
digz6666

[Err] 22018 - [SQL Server] ไม่อนุญาตให้มีการแปลงอย่างชัดเจนจากชนิดข้อมูล xml เป็นข้อความ
digz6666

ฟังดูเหมือนคุณทำอะไรผิด @ digz6666
Squazz

1
@Squazz คุณโหวตคำตอบนี้ล่าสุดเมื่อวานนี้ ขณะนี้การโหวตของคุณถูกล็อกเว้นแต่จะมีการแก้ไขคำตอบนี้ :)
digz6666

10

อีกทางเลือกหนึ่งคือการค้นหา XML เป็นสตริงโดยการแปลงเป็นสตริงแล้วใช้ LIKE อย่างไรก็ตามเนื่องจากคอลัมน์จากการคำนวณไม่สามารถเป็นส่วนหนึ่งของคำสั่ง WHERE ได้คุณจึงต้องรวมไว้ใน SELECT อื่นเช่นนี้:

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

โปรดทราบว่าสิ่งนี้อาจข้ามดัชนี xml แบบเลือกใด ๆ ที่คุณอาจมีอยู่และได้รับผลกระทบจากประสิทธิภาพ
Rudy Hinojosa

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 (... )
marc_s
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.