Reputation: 5894
We have a simple table (an audit log) that our (3rd-party) product fills with data. The problem is that the data appears to be an XML serialisation of data, stored in a varchar(max())
column.
CREATE TABLE Audit (
AuditID int IDENTITY,
AuditData nvarchar(max) NULL
)
The data AuditData then looks a bit like this:
<DELETED customerId="89"
username="alice"
firstname="Alice"
lastname="WTF"
field1="..."
field2="..."
fieldn="..."
/>
Is there any sensible way of getting at this data from SQL queries? For example let us say I want to get all audit records where the customerId is 89.
I don't want to have to resort to string mangling if I can possibly help it!
-- This is bad:
SELECT AuditID, AuditData
FROM Audit
WHERE AuditData LIKE '%customerId="89"%'
Upvotes: 1
Views: 4185
Reputation: 2216
DECLARE @MyXML XML
SET @MyXML = `<DELETED
customerId="89"
username="alice"
firstname="Alice"
lastname="WTF"
field1="..."
field2="..."
fieldn="..."
/>`
SELECT
a.b.value(`'@customerId'`,`'varchar(10)'`) AS customerId
FROM @MyXML.nodes(`'DELETED'`) a(b)
Upvotes: 0
Reputation: 138960
It would easier/faster if AuditData
was an XML column but you can cast it in the query.
select AuditID, AuditData
from Audit
where cast(AuditData as xml).value('(/DELETED/@customerId)[1]', 'int') = 89
Note:
This requires that AuditData
column contains valid XML for all rows in the table. (NULL is ok) and SQL Server 2005 or higher.
If you want to filter on customerId
regardless of the root node name you can use this instead.
select AuditID, AuditData
from Audit
where cast(AuditData as xml).value('(/*/@customerId)[1]', 'int') = 89
Upvotes: 7