XQuery: Finding rows which contain specified xml d

2019-05-10 23:19发布

I have a table which contains many rows, each with a column named "RecordData" that contains XML data that I wish to search upon.

Three rows worth of example xml data from this column is given below:

1:

<Record>
  <RecordField ID="31" Name="Barcode1" DataTypeId="5" TypeName="String" Decimals="0" Format="" Mandatory="False">ABC123</RecordField>
</Record>

2:

<Record>
  <RecordField ID="15" Name="Field 1" DataTypeId="7" TypeName="Boolean" Decimals="0" Format="" Mandatory="False">true</RecordField>
  <RecordField ID="16" Name="Field 2" DataTypeId="5" TypeName="String" Decimals="0" Format="" Mandatory="False">purpke</RecordField>
</Record>

3:

<Record>
  <RecordField ID="15" Name="Field 1" DataTypeId="7" TypeName="Boolean" Decimals="0" Format="" Mandatory="False">true</RecordField>
  <RecordField ID="16" Name="Field 2" DataTypeId="5" TypeName="String" Decimals="0" Format="" Mandatory="False">12</RecordField>
</Record>

I am using the following SQL to try and find any table rows, that have XML data that contains a specific search term ('1' in this example).

DECLARE @SearchTerm varchar(max)
    SET @SearchTerm = '1'
    SELECT * 
    FROM MyTableOfData
    WHERE RecordFields.value('contains( (/Record/RecordField/text())[1],sql:variable("@SearchTerm"))','bit') = 1

As you will see, this relies on the search term appearing in the first "RecordField" element's text, rather than searching over ALL of the "RecordField" nodes. Meaning, the only result I get back would be row 1, rather than both rows 1 and 3.

I've done a bit of reading through the related MSDN articles, and am having a Google-fail day, as I'm not getting any closer to finding out how to remove the limitation and finally crack this.

Any help would be greatly appreciated :)

EDIT:

DECLARE @SearchTerm varchar(max)
SET @SearchTerm = '1'
select *
from MyTableOfData
    cross apply MyTableOfData.RecordFields.nodes('/Record/RecordField') as tx(r)
where  tx.r.value('.','varchar(10)') like '%'+@searchterm+'%'

throws:

Msg 493, Level 16, State 1, Line 3
The column 'r' that was returned from the nodes() method cannot be used directly. It can only be used with one of the four XML data type methods, exist(), nodes(), query(), and value(), or in IS NULL and IS NOT NULL checks.

EDIT 2:

And when you copy exactly what you're told, instead of missing things, this works!:

DECLARE @SearchTerm varchar(max)
SET @SearchTerm = '1'
select MyTableOfData.*
from MyTableOfData
    cross apply MyTableOfData.RecordFields.nodes('/Record/RecordField') as tx(r)
where  tx.r.value('.','varchar(10)') like '%'+@searchterm+'%'

2条回答
倾城 Initia
2楼-- · 2019-05-10 23:42

CROSS APPLY is what you've failed to find...

select yourtable.*
from yourtable
    cross apply yourtable.RecordFields.nodes('/Record/RecordField') as tx(r)
where  tx.r.value('.','varchar(10)') like '%'+@searchterm+'%'

or

where tx.r.value('contains((.),sql:variable("@searchterm"))','bit')=1
查看更多
戒情不戒烟
3楼-- · 2019-05-11 00:01

You can use exist.

select *
from MyTableOfData
where RecordFields.exist('/Record/RecordField[contains(., sql:variable("@SearchTerm"))]') = 1
查看更多
登录 后发表回答