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+'%'
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
You can use exist.
select *
from MyTableOfData
where RecordFields.exist('/Record/RecordField[contains(., sql:variable("@SearchTerm"))]') = 1
来源:https://stackoverflow.com/questions/11738010/xquery-finding-rows-which-contain-specified-xml-data