Chris
Chris

Reputation: 1

TSQL - Need to query a database column which is populated by XML

TSQL - Need to query a database column which is populated by XML.

The Database has an iUserID column with an Application ID and VCKey

TxtValue is the Column name and the contained Data is similar to this

<BasePreferencesDataSet xmlns="http://tempuri.org/BasePreferencesDataSet.xsd">
<ViewModesTable>
<iViewID>1</iViewID>
</ViewModesTable>
<ViewMode_PreferenceData>
<iViewID>1</iViewID>
<iDataID>0</iDataID>
<strValue>False</strValue>
</ViewMode_PreferenceData>
<ViewMode_PreferenceData>
<iViewID>1</iViewID>
<iDataID>5</iDataID>
<strValue>True</strValue>
</ViewMode_PreferenceData>
<ViewMode_PreferenceData>
<iViewID>1</iViewID>
<iDataID>6</iDataID>
<strValue>True</strValue>
</ViewMode_PreferenceData> 
<ViewMode_PreferenceData>
<iViewID>1</iViewID>
<iDataID>4</iDataID>
<strValue>False</strValue> 

I want to be able to identify any iUserID in which the StrValue for iDataID's 5 and 6 are not set to True.

I have attempted to use a txtValue Like % statement but even if I copy the contents and query for it verbatim it will not yield a result leading me to believe that the XML data cannot be queried in this manner.

Screenshot of Select * query for this DB for reference

Upvotes: 0

Views: 72

Answers (2)

Gottfried Lesigang
Gottfried Lesigang

Reputation: 67291

You can try XML-method .exist() together with an XPath with predicates:

WITH XMLNAMESPACES(DEFAULT 'http://tempuri.org/BasePreferencesDataSet.xsd') 
SELECT * 
FROM YourTable
WHERE CAST(txtValue AS XML).exist('/BasePreferencesDataSet
                                   /ViewMode_PreferenceData[iDataID=5 or iDataID=6]
                                   /strValue[text()!="True"]')=1;

The namespace-declaration is needed to address the elements without a namespace prefix.

The <ViewMode_PreferenceData> is filtered for the fitting IDs, while the <strValue> is filtered for a content !="True". This will return any data row, where there is at least one entry, with an ID of 5 or 6 and a value not equal to "True".

Upvotes: 1

Stuart Ainsworth
Stuart Ainsworth

Reputation: 12940

So without sample data (including tags; sorry you're having trouble with that) it's tough to craft the complete query, but what you're looking for is XQuery, specifically the .exists method in T-SQL.

Something like

SELECT iUserID
FROM tblLocalUserPreferences
WHERE iApplicationID = 30 
AND vcKey='MonitorPreferences'
AND (txtValue.exist('//iDataID[text()="5"]/../strValue[text()="True"]') = 0
      OR txtValue.exist('//iDataID[text()="6"]/../strValue[text()="True"]')=0)

This should return all userID's where either iDataID 5 or 6 do NOT contain True. In other words, if both are true, you won't get that row back.

Upvotes: 0

Related Questions