I need to pull information from the “Name” element from an XML column in SQL. An example of the XML is below:
<ArrayOfTarget xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes"> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true" /> <Id>19bc33e1-a788-cd99-3dab-08d92aa7d030</Id> <Name>Case Number WB21-006637</Name> <Type>Case Management</Type> </Target> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true" /> <Id>cb4d829b-c31a-cadb-5c9e-08d934b7404d</Id> <Name>Incident Supplement Number WB21-006637.006</Name> <Type>Data Entry</Type> </Target> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true" /> <Id>6b23195c-4650-c0c9-925d-08d71a88f611</Id> <Name i:nil="true" /> <Type>Template</Type> </Target> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true" /> <Id>b465517c-5926-c6b3-1cc6-08d6fbe6da27</Id> <Name>Default Workflow</Name> <Type>Workflow</Type> </Target> <Target> <AgencyId i:nil="true" /> <AgencyName i:nil="true" /> <Id i:nil="true" /> <Name>Complete</Name> <Type>Workflow Step</Type> </Target> </ArrayOfTarget>
I have this SQL Query which works for returning five of the “Name” elements:
;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS i, 'http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes' AS s) SELECT TOP 100 TargetData_Xml, Description, TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[1]', 'varchar(100)') as Context1, TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[2]', 'varchar(100)') as Context2, TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[3]', 'varchar(100)') as Context3, TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[4]', 'varchar(100)') as Context4, TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[5]', 'varchar(100)') as Context5 FROM [InformRMSAudit].[dbo].[AuditEntities] WHERE CaseNumber = 'RP21-010802' ORDER BY Date desc
That would be sufficient if every record had only five “Name” elements in the XML, but the number of “Name” elements varies from record to record.
How could I change my query to handle the variation from record to record?
Advertisement
Answer
Please try the following solution.
As @Larnu pointed out, it is much better to shred the XML as rows.
If needed it is very easy to filter out names with NULL values.
SQL
-- DDL and sample data population, start DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, TargetData_Xml XML); INSERT INTO @tbl (TargetData_Xml) VALUES (N'<ArrayOfTarget xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes"> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true"/> <Id>19bc33e1-a788-cd99-3dab-08d92aa7d030</Id> <Name>Case Number WB21-006637</Name> <Type>Case Management</Type> </Target> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true"/> <Id>cb4d829b-c31a-cadb-5c9e-08d934b7404d</Id> <Name>Incident Supplement Number WB21-006637.006</Name> <Type>Data Entry</Type> </Target> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true"/> <Id>6b23195c-4650-c0c9-925d-08d71a88f611</Id> <Name i:nil="true"/> <Type>Template</Type> </Target> <Target> <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId> <AgencyName i:nil="true"/> <Id>b465517c-5926-c6b3-1cc6-08d6fbe6da27</Id> <Name>Default Workflow</Name> <Type>Workflow</Type> </Target> <Target> <AgencyId i:nil="true"/> <AgencyName i:nil="true"/> <Id i:nil="true"/> <Name>Complete</Name> <Type>Workflow Step</Type> </Target> </ArrayOfTarget>'); -- DDL and sample data population, end WITH XMLNAMESPACES (DEFAULT 'http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes') SELECT ID , c.value('(Name/text())[1]', 'VARCHAR(100)') AS [Name] FROM @tbl CROSS APPLY TargetData_Xml.nodes('/ArrayOfTarget/Target') AS t(c);
Output
+----+--------------------------------------------+ | ID | Name | +----+--------------------------------------------+ | 1 | Case Number WB21-006637 | | 1 | Incident Supplement Number WB21-006637.006 | | 1 | NULL | | 1 | Default Workflow | | 1 | Complete | +----+--------------------------------------------+