SQL Server query xml column - sql-server

I need to pull values from an XML column. The table contains 3 fields with one being an XML column like below:
TransID int,
Place varchar(20),
Custom XML
The XML column is structured as following:
<Fields>
<Field>
<Id>9346-00155D1C204E</Id>
<TransactionCode>0710</TransactionCode>
<Amount>5.0000</Amount>
</Field>
<Field>
<Id>A6F0-BA07EF3A7D43</Id>
<TransactionCode>0885</TransactionCode>
<Amount>57.9000</Amount>
</Field>
<Field>
<Id>9BDA-7858FD182Z3C</Id>
<TransactionCode>0935</TransactionCode>
<Amount>25.85000</Amount>
</Field>
</Fields>
I need to be able to query the xml column and return only the value for the <Amount> if there is a <Transaction code> = 0935. Note: there are records where this transaction code isn’t present, but it won't exist in the same record twice.
This is probably simple, but I’m having a problem returning just the <amount> value where the <transaction code> = 0935.

You can try this way :
DECLARE #transCode VARCHAR(10) = '0935'
SELECT field.value('Amount[1]', 'decimal(18,5)') as Amount
FROM yourTable t
OUTER APPLY t.Custom.nodes('/Fields/Field[TransactionCode=sql:variable("#transCode)"]') as x(field)
Alternatively, you can put logic for filtering Field by TransactionCode in SQL WHERE clause instead of in XPath expression, like so :
DECLARE #transCode VARCHAR(10) = '0935'
SELECT field.value('Amount[1]', 'decimal(18,5)') as Amount
FROM yourTable t
OUTER APPLY t.Custom.nodes('/Fields/Field') as x(field)
WHERE field.value('TransactionCode[1]', 'varchar(10)') = #transCode
SQL Fiddle Demo

You can use an XPath like this in your TSQL:
SELECT
*,
Custom.value('(/Fields/Field[#Name="Id"]/#Value)[1]', 'varchar(50)')
FROM YourTable
WHERE Custom.value('(/Fields/Field[#Name="Id"]/#Value)[1]', 'varchar(50)') = '0655'

Related

T-SQL: Parse XML Data in from classes which inherit from a common base,

I'm trying to parse XML data in SQL Server. I have a XML column in a table, the XML stored in it can vary by type, but they all inherit from the same base type.
Row 1: has XML like so:
<Form>
<TaskType>1</TaskType>
--Other Properties ...
</Form>
Row 2: has XML like so:
<License>
<TaskType>2</TaskType>
--Other Properties ...
</License>
Normally I might parse XML with this T-SQL code snippet:
SELECT
xmlData.A.value('.', 'INT') AS Animal
FROM
#XMLToParse.nodes('License/TaskType') xmlData(A)
This doesn't work since in a view since I'm dependent on the name to find the node.
How can I always find the TaskType XML element in my XML content?
Please try the following solution.
XPath is using asterisk * as a wildcard.
http://www.tizag.com/xmlTutorial/xpathwildcard.php
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT #tbl (xmldata) VALUES
(N'<Form>
<TaskType>1</TaskType>
<TaskName>Clone</TaskName>
<!--Other XML elements-->
</Form>'),
(N'<License>
<TaskType>2</TaskType>
<TaskName>Copy</TaskName>
<!--Other XML elements-->
</License>');
-- DDL and sample data population, end
SELECT ID
, c.value('(TaskType/text())[1]', 'INT') AS TaskType
, c.value('(TaskName/text())[1]', 'VARCHAR(20)') AS TaskName
FROM #tbl
CROSS APPLY xmldata.nodes('/*') AS t(c);
Output
ID
TaskType
TaskName
1
1
Clone
2
2
Copy
Apparently you can just interate the nodes like so without being aware of their name:
SELECT xmlData.A.value('.', 'INT') AS Animal
FROM #XMLToParse.nodes('node()/TaskType') xmlData(A)

SQL Server parse XML column to get a column value if other column value equals certain value

In SQL Server 2014 a table with a CustomColumns column that contains XML data with the following structure:
<CustomColumnsCollection>
<CustomColumn>
<Name>Brand</Name>
<DataType>0</DataType>
<Value>Duprim</Value>
</CustomColumn>
<CustomColumn>
<Name>LabelGroup</Name>
<DataType>0</DataType>
<Value />
</CustomColumn>
...
</CustomColumnsCollection>
I want to get value of column Value where column Name equals, i.e. 'Brand' (the following code is a part of bigger query, which I saved as VIEW):
MAX(DISTINCT PR.CustomColumns.value('(/CustomColumnsCollection/CustomColumn/Name="Brand"/Value)[0]', 'varchar(max)')) AS Brand
In this case I would like it to return 'Duprim'. How is this achieved?
Here is another method by using XPath predicate.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, CustomColumns XML);
INSERT INTO #tbl (CustomColumns)
VALUES
(N'<CustomColumnsCollection>
<CustomColumn>
<Name>Brand</Name>
<DataType>0</DataType>
<Value>Duprim</Value>
</CustomColumn>
<CustomColumn>
<Name>LabelGroup</Name>
<DataType>0</DataType>
<Value/>
</CustomColumn>
</CustomColumnsCollection>');
-- DDL and sample data population, end
DECLARE #param VARCHAR(30) = 'Brand';
SELECT ID
, c.value('(Value/text())[1]', 'VARCHAR(50)') AS [Value]
FROM #tbl
CROSS APPLY CustomColumns.nodes('/CustomColumnsCollection/CustomColumn[(Name/text())[1] eq sql:variable("#param")]') AS t(c);
-- hard-coded value
SELECT ID
, c.value('(Value/text())[1]', 'VARCHAR(50)') AS [Value]
FROM #tbl
CROSS APPLY CustomColumns.nodes('/CustomColumnsCollection/CustomColumn[(Name/text())[1] eq "Brand"]') AS t(c);
Output
+----+--------+
| ID | Value |
+----+--------+
| 1 | Duprim |
+----+--------+
To help you with the view that is consumed by the MS Excel.
It would be great if you could provide a minimal reproducible example:
(1) DDL and sample data population, i.e. CREATE table(s) plus INSERT, T-SQL statements.
(2) What you need to do, i.e. logic.
(3) Desired output based on the sample data in #1 above.
SQL for Excel
SELECT ID
, CustomColumns.value('(/CustomColumnsCollection/CustomColumn[(Name/text())[1] eq "Brand"]/Value/text())[1]', 'VARCHAR(50)') AS [Value]
FROM #tbl;
Try something like this:
SELECT
xc.value('(Value)[1]', 'varchar(50)')
FROM
PR
CROSS APPLY
PR.CustomColumns.nodes('/CustomColumnsCollection/CustomColumn') AS XT(XC)
WHERE
xc.value('(Name)[1]', 'varchar(50)') = 'Brand'
The .nodes() returns a list of XML fragments, each representing a <CustomColumn> node. Select the one with the Name value of Brand in the WHERE clause, and get the value of Value for that XML node

Unable to save data from xml format in SQL table

SELECT *
FROM #myHierarchy
FOR XML AUTO
Data is
<_x0040_myHierarchy element_id="1" parent_ID="1" NAME="itemCode" StringValue="Simmi" ValueType="string" />
I'm unable to load data in this query
SELECT #xml = dbo.ToXML(#myHierarchy);
SELECT
a.b.value('#ItemCode', 'varchar(20)') AS ItemCode
FROM
#xml.nodes('/root/_x0040_myHierarchy') a(b)
In this query, itemcode is blank. How can I load data using this query?
Your sample XML does not contain any attribute ItemCode - it has these attributes:
element_id
parent_ID
NAME
StringValue
ValueType
So which value do you really want to read out from the XML element?
Update: to retrieve the StringValue attribute, use this code:
SELECT
XC.value('#StringValue', 'varchar(50)')
FROM
#xml.nodes('/_x0040_myHierarchy') AS XT(XC)
If your XML contains a <root> ..... </root> root element, and multiple <_x0040_myHierarchy> elements inside, and you want to extract the one with #Name = 'itemCode' - then you need to use this SELECT:
SELECT
XC.value('#StringValue', 'varchar(50)')
FROM
#xml.nodes('/root/_x0040_myHierarchy') AS XT(XC)
WHERE
XC.value('#NAME', 'varchar(50)') = 'itemCode'

XML to SQL Tables without explicit column names

I'm trying to insert data into SQL using XML. I've managed to figure out the insert operation like so.
create table #testTable (name varchar(50), designation varchar(50));
declare #xmldata as xml
set #xmldata = '<?xml version="1.0"?>
<Employees>
<Employee name="John" designation="SE"></Employee>
<Employee name="Adam" designation="ASE"></Employee>
</Employees>'
insert into #testTable
select 
  r.value('#name', 'varchar(50)'),
  r.value('#designation', 'varchar(50)')
from #xmldata.nodes('/Employees/Employee') t(r)
Using this method, I am required to pre-specify the column names when I use the value method manually.
What I want is a method to run this query without specifying the columns explicitly in the value() method and get a table with the XML attributes as the column names and the values as the data. I am willing to convert this to typed XML if it gets the job done. Assume that the xml columns will always conform to my existing table.
Thanks in advance.

Select XML from varchar(max) column

I have some XML data stored in a varchar(max) column on SQL Server 2005. The data is in the form (FQTN = fully qualified type name):
<?xml version="1.0" encoding="utf-16"?>
<History xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EntityViews>
<EntityProxy Type="FQTN" Key="386876" />
<EntityProxy Type="FQTN" Key="387981" />
<!-- etc. -->
</EntityViews>
</History>
How can I select Type, Key so that I get a tabular result from the XML data in this column for a single row? The table has an identity primary key named HistoryId.
;with cteCastToXML as (
select CAST(YourColumn as xml) as x
from YourTable
)
select h.ep.value('#Type','varchar(10)') as [Type],
h.ep.value('#Key', 'varchar(10)') as [Key]
from cteCastToXML
cross apply x.nodes('/History/EntityViews/EntityProxy') as h(ep)
My recommendation would be two fold.
If this is what you will be doing with the column, change the column to be an XML column.
If you need to do this one time, look at taking the value and converting it to XML, then you can operate on it like you would normally. (Here is a link on how to convert).

Resources