Sử dụng câu lệnh LIKE trên SQL Server XML Datatype


86

Nếu bạn có trường varchar, bạn có thể dễ dàng SELECT * FROM TABLE WHERE ColumnA LIKE '%Test%'xem cột đó có chứa một chuỗi nhất định hay không.

Làm thế nào để bạn làm điều đó cho Loại XML?

Tôi có phần sau chỉ trả về các hàng có nút 'Văn bản' nhưng tôi cần tìm kiếm trong nút đó

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

Câu trả lời:


70

Bạn sẽ có thể làm điều này khá dễ dàng:

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

Các .valuephương pháp mang đến cho bạn giá trị thực tế, và bạn có thể xác định rằng để được trả lại như một VARCHAR (), sau đó bạn có thể kiểm tra với một tuyên bố tương tự.

Xin lưu ý bạn, điều này sẽ không nhanh đến mức khủng khiếp. Vì vậy, nếu bạn có một số trường nhất định trong XML của mình mà bạn cần phải kiểm tra nhiều, bạn có thể:

  • tạo một hàm được lưu trữ để lấy XML và trả về giá trị bạn đang tìm kiếm dưới dạng VARCHAR ()
  • xác định một trường được tính toán mới trên bảng của bạn, trường này gọi hàm này và đặt nó thành cột ĐƯỢC LẬP KIỆN

Với điều này, về cơ bản bạn sẽ "trích xuất" một phần nhất định của XML vào một trường được tính toán, làm cho nó tồn tại và sau đó bạn có thể tìm kiếm rất hiệu quả trên đó (heck: bạn thậm chí có thể INDEX trường đó!).

Marc


1
Về cơ bản, tôi đang áp dụng một tính năng tìm kiếm, vì vậy tôi muốn chỉ tìm kiếm cột XML trên các nút 'Văn bản' và sau đó trả về một chuỗi con để cho biết rằng tìm kiếm đã tìm thấy kết quả phù hợp. Ví dụ: tìm kiếm trên 'xin chào' thay vì trả về toàn bộ cột xml, tôi chỉ trả về một chuỗi con chẳng hạn như 'chương đã nói xin chào ở đó và mang theo ...'
Jon

1
Đánh bại tôi trước 5 giây. Một khả năng khác là để xem xét sử dụng tìm kiếm văn bản miễn phí, nếu dữ liệu của bạn tuân theo ...
RickNZ

10
để tìm kiếm toàn bộ hồ sơ: WHERE xmlField.value ('.', 'varchar (max)') THÍCH '% FOO%'
jhilden

xem ra cho các namespaces Xml pesky nếu bạn nhận được NULL trở lại
Simon_Weaver

86

Tuy nhiên, một tùy chọn khác là truyền XML dưới dạng nvarchar, và sau đó tìm kiếm chuỗi đã cho như thể XML vas là trường nvarchar.

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

Tôi thích giải pháp này vì nó rõ ràng, dễ nhớ, khó lộn xộn và có thể được sử dụng như một phần của mệnh đề where.

CHỈNH SỬA: Khi Cliff đề cập đến nó, bạn có thể sử dụng:

... nvarchar nếu có các ký tự không chuyển đổi thành varchar


3
Ditto trên đó, hoặc nvarchar nếu có nhân vật mà không chuyển đổi sang varchar SELECT * FROM table WHERE CAST (Cột như nvarchar (max)) LIKE '% THI%'
Cliff Coulter

[Err] 42000 - [SQL Server] Chuyển đổi một hoặc nhiều ký tự từ XML để mục tiêu đối chiếu bất khả thi
digz6666

[Err] 22018 - [SQL Server] Không cho phép chuyển đổi rõ ràng từ kiểu dữ liệu xml sang văn bản.
digz6666

Có vẻ như bạn đang làm sai điều gì đó @ digz6666
Squazz

1
@Squazz Lần cuối cùng bạn đã bỏ phiếu cho câu trả lời này vào ngày hôm qua. Phiếu bầu của bạn hiện đã bị khóa trừ khi câu trả lời này được chỉnh sửa. :)
digz6666

10

Một tùy chọn khác là tìm kiếm XML dưới dạng một chuỗi bằng cách chuyển đổi nó thành một chuỗi và sau đó sử dụng LIKE. Tuy nhiên, vì một cột được tính không thể là một phần của mệnh đề WHERE, bạn cần phải bọc nó trong một SELECT khác như thế này:

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

Lưu ý rằng điều này có thể bỏ qua bất kỳ chỉ mục xml chọn lọc nào mà bạn có thể có và ảnh hưởng đến hiệu suất.
Rudy Hinojosa

0

Đây là những gì tôi sẽ sử dụng dựa trên câu trả lời 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

Trả về một chuỗi con trên tìm kiếm có tiêu chí tìm kiếm


Tôi có cần các thông số để ngăn chặn tiêm bằng cách nào đó không?
Jon

2
HÃY NHẬN THỨC: những hàm XML đó KHÔNG phân biệt chữ hoa chữ thường - DATA.VALUE sẽ không hoạt động! Nó cần phải là .value (...)
marc_s
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.