Làm cách nào tôi có thể truy vấn một giá trị trong cột SQL Server XML


127

Tôi đã theo dõi XML được lưu trữ trong một cột XML (được gọi Roles) trong cơ sở dữ liệu SQL Server.

<root>
   <role>Alpha</role>
   <role>Beta</role>
   <role>Gamma</role>
</root>

Tôi muốn liệt kê tất cả các hàng có vai trò cụ thể trong đó. Vai trò này được thông qua bởi tham số.

Câu trả lời:


198
select
  Roles
from
  MyTable
where
  Roles.value('(/root/role)[1]', 'varchar(max)') like 'StringToSearchFor'

Các trang này sẽ cho bạn biết thêm về cách truy vấn XML trong T-SQL:

Truy vấn các trường XML bằng cách sử dụng t-sql

Làm phẳng dữ liệu XML trong SQL Server

BIÊN TẬP

Sau khi chơi với nó thêm một chút nữa, tôi đã kết thúc với truy vấn tuyệt vời này sử dụng CROSS ỨNG DỤNG . Cái này sẽ tìm kiếm mọi hàng (vai trò) cho giá trị bạn đặt trong biểu thức thích của bạn ...

Cho cấu trúc bảng này:

create table MyTable (Roles XML)

insert into MyTable values
('<root>
   <role>Alpha</role>
   <role>Gamma</role>
   <role>Beta</role>
</root>')

Chúng ta có thể truy vấn nó như thế này:

select * from 

(select 
       pref.value('(text())[1]', 'varchar(32)') as RoleName
from 
       MyTable CROSS APPLY

       Roles.nodes('/root/role') AS Roles(pref)
)  as Result

where RoleName like '%ga%'

Bạn có thể kiểm tra SQL Fiddle tại đây: http://sqlfiddle.com/#!18/dc4d2/1/0


5
Nó trả lời tất cả câu hỏi của tôi, [1]làm gì trong câu trả lời của bạn?
Bistro

1
Câu trả lời tuyệt vời, tôi bỏ phiếu cho câu hỏi này, nhưng chuỗi nên là varchar tôi đoán
AaA

7
@Bistro Hỏi về [1]là một câu hỏi thực sự tốt. Điều đó có nghĩa là bạn chọn giá trị vai trò đầu tiên từ XML và điều đó có nghĩa là điều này sẽ chỉ hoạt động để tìm Alphatrong xml mẫu của bạn. Nó sẽ không tìm thấy hàng nếu bạn tìm kiếm Beta.
Mikael Eriksson

1
Trong trường hợp của tôi, tôi đã phải truy vấn các nút có giá trị thuộc tính cụ thể. Câu trả lời này đã dẫn đến giải pháp của tôi. Tôi chỉ phải đặt dấu ngoặc kép xung quanh giá trị thuộc tính.
John N

Nếu XML có một không gian tên, làm thế nào để chúng ta truy vấn nó?
FMFF

36
declare @T table(Roles xml)

insert into @T values
('<root>
   <role>Alpha</role>
   <role>Beta</role>
   <role>Gamma</role>
</root>')

declare @Role varchar(10)

set @Role = 'Beta'

select Roles
from @T
where Roles.exist('/root/role/text()[. = sql:variable("@Role")]') = 1

Nếu bạn muốn truy vấn hoạt động như where col like '%Beta%'bạn có thể sử dụngcontains

declare @T table(Roles xml)

insert into @T values
('<root>
   <role>Alpha</role>
   <role>Beta</role>
   <role>Gamma</role>
</root>')

declare @Role varchar(10)

set @Role = 'et'

select Roles
from @T
where Roles.exist('/root/role/text()[contains(., sql:variable("@Role"))]') = 1

13

nếu tên trường của bạn là Vai trò và tên bảng là bảng1, bạn có thể sử dụng theo sau để tìm kiếm

DECLARE @Role varchar(50);
SELECT * FROM table1
WHERE Roles.exist ('/root/role = sql:variable("@Role")') = 1

Điều này là tốt, ở đây có cách nào để tìm kiếm bằng cách sử dụng like? forexample /root/role like ....
Bistro

2
sử dụng .value('(/root/role)[1]', 'varchar(max)') like '%yourtext%'thay vì existsnhư Leniel đã giải thích
AaA

4
Bạn đã thử điều này? Nó tìm thấy mọi thứ, bất kể những gì bạn đặt vào @Role.
Mikael Eriksson

6

Tôi đã nghĩ ra một công việc đơn giản xung quanh bên dưới cũng dễ nhớ :-)

select * from  
(select cast (xmlCol as varchar(max)) texty
 from myTable (NOLOCK) 
) a 
where texty like '%MySearchText%'

1
Chúng tôi không được phép tìm kiếm thông qua thao tác chuỗi, vì điều đó sẽ dẫn đến việc tìm kiếm quá chậm
Malcolm Salvador

5

Bạn có thể làm như sau

declare @role varchar(100) = 'Alpha'
select * from xmltable where convert(varchar(max),xmlfield) like '%<role>'+@role+'</role>%'

Rõ ràng đây là một chút hack và tôi sẽ không đề xuất nó cho bất kỳ giải pháp chính thức nào. Tuy nhiên, tôi thấy kỹ thuật này rất hữu ích khi thực hiện các truy vấn adhoc trên các cột XML trong SQL Server Management Studio cho SQL Server 2012.


2

Lời khuyên hữu ích. Truy vấn một giá trị trong cột XML của SQL Server (XML có không gian tên)

ví dụ

Table [dbo].[Log_XML] contains columns Parametrs (xml),TimeEdit (datetime)

ví dụ: XML trong Parametrs:

<ns0:Record xmlns:ns0="http://Integration"> 
<MATERIAL>10</MATERIAL> 
<BATCH>A1</BATCH> 
</ns0:Record>

ví dụ: Truy vấn:

select
 Parametrs,TimeEdit
from
 [dbo].[Log_XML]
where
 Parametrs.value('(//*:Record/BATCH)[1]', 'varchar(max)') like '%A1%'
 ORDER BY TimeEdit DESC

1

Tôi đã sử dụng câu lệnh dưới đây để lấy các giá trị trong XML trong bảng Sql

with xmlnamespaces(default 'http://test.com/2008/06/23/HL.OnlineContract.ValueObjects')
select * from (
select
            OnlineContractID,
            DistributorID,
            SponsorID,
    [RequestXML].value(N'/OnlineContractDS[1]/Properties[1]/Name[1]', 'nvarchar(30)') as [Name]
   ,[RequestXML].value(N'/OnlineContractDS[1]/Properties[1]/Value[1]', 'nvarchar(30)') as [Value]
     ,[RequestXML].value(N'/OnlineContractDS[1]/Locale[1]', 'nvarchar(30)') as [Locale]
from [OnlineContract]) as olc
where olc.Name like '%EMAIL%' and olc.Value like '%EMAIL%' and olc.Locale='UK EN'

Điều gì xảy ra nếu XML không chứa định nghĩa Namespace?
Muflix

0

Bạn có thể truy vấn toàn bộ thẻ, hoặc chỉ giá trị cụ thể. Ở đây tôi sử dụng ký tự đại diện cho các không gian tên xml.

declare @myDoc xml
set @myDoc = 
'<Root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://stackoverflow.com">
    <Child>my value</Child>
 </Root>'

select @myDoc.query('/*:Root/*:Child') -- whole tag
select @myDoc.value('(/*:Root/*:Child)[1]', 'varchar(255)') -- only value
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.