Separate XML node values into separate rows in SQL - sql

I have a SQL table with a XML column. The value of the column looks like this:
<StudentGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<StudentIds>
<int>3000</int>
<int>3001</int>
<int>3002</int>
<int>8</int>
<int>9</int>
</StudentIds>
</StudentGroup>
I want to get the each StudentIDs in a separate row instead of it in one row. Here is what I have done:
select
xmlColumn.value('(/StudentGroup/StudentIds)[1]','varchar(max)') as IDs
from myTable
This select statement returns the IDs in one row. Like this:
30003001300289
What is want is
3000
3001
3002
8
9
Please help! Thanks in advance.

When you have the XML in a variable:
DECLARE #x XML = '
<StudentGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<StudentIds>
<int>3000</int>
<int>3001</int>
<int>3002</int>
<int>8</int>
<int>9</int>
</StudentIds>
</StudentGroup>';
SELECT
n.v.value('.','INT') AS ID
FROM
#x.nodes('/StudentGroup/StudentIds/int') AS n(v);
When you have the XML in a table:
DECLARE #x XML = '
<StudentGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<StudentIds>
<int>3000</int>
<int>3001</int>
<int>3002</int>
<int>8</int>
<int>9</int>
</StudentIds>
</StudentGroup>';
DECLARE #t TABLE(
x XML
);
INSERT INTO #t(x)VALUES(#x);
SELECT
n.v.value('.','INT') AS ID
FROM
#t
CROSS APPLY x.nodes('/StudentGroup/StudentIds/int') AS n(v);

Related

Selecting XML nodes with SQL Server

My XMLData is stored under table.[column] : dbo.promotions.[PromotionDiscountData]
and the XML looks like the following when i expand it:
<ArrayOfPromotionDiscountBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PromotionDiscountBase xsi:type="OrderPromotionDiscount">
<DiscountType>Fixed</DiscountType>
<DiscountAmount>5.0000</DiscountAmount>
</PromotionDiscountBase>
</ArrayOfPromotionDiscountBase>
I would like to export a report and flatten out the xml as a column with everything else in the dbo.promotions table.
What would be the best way to get the DiscountType and DiscountAmount Out of the xml?
Thanks!
Please try the following.
SQL
-- DDL and data population, start
DECLARE #tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY,[xmlData] XML NOT NULL);
INSERT INTO #tbl([xmlData])
VALUES
(N'<ArrayOfPromotionDiscountBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PromotionDiscountBase xsi:type="OrderPromotionDiscount">
<DiscountType>Fixed</DiscountType>
<DiscountAmount>5.0000</DiscountAmount>
</PromotionDiscountBase>
</ArrayOfPromotionDiscountBase>');
-- DDL and data population, end
SELECT ID
, col.value('(DiscountType)[1]', 'VARCHAR(30)') AS [DiscountType]
, col.value('(DiscountAmount)[1]', 'DECIMAL(10,4)') AS [DiscountAmount]
FROM #tbl AS tbl
CROSS APPLY tbl.[xmlData].nodes('/ArrayOfPromotionDiscountBase/PromotionDiscountBase') AS tab(col);

How to get value of an XML tag of varchar(MAX) string type?

I am working with SQL Server 2016.
I have a table employee_xml which has a column employee_xml_string of varchar(MAX) type.
CREATE TABLE employee_xml
(
employee_xml_id INT IDENTITY(1,1) NOT NULL,
employee_xml_string VARCHAR(MAX)
);
employee_xml_string column stores an XML string; for example:
<?xml version="1.0" encoding="UTF-8"?>
<Employees xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Employee>
<EmployeeNumber>58913A</EmployeeNumber>
<FirstName>Shanee</FirstName>
<LastName>McKenzie</LastName>
<GovernmentIdentificationNumber>749146551</GovernmentIdentificationNumber>
</Employee>
</Employees>
I want to write SQL to get the value of <GovernmentIdentificationNumber> tag. How can I do that?
Thanks
You'll have to CAST/CONVERT the value of your XML to xml (so I hope they're all valid XML values) and then you can use XQUERY against that converted value:
SELECT V.Employee_XML.value('(Employees/Employee/GovernmentIdentificationNumber/text())[1]','int') AS GovernmentIdentificationNumber
FROM dbo.employee_xml E
CROSS APPLY (VALUES(TRY_CONVERT(xml,E.employee_xml_string))) V(Employee_XML);
Ideally, however, you should be storing XML data as an xml; that's what it's there for after all.
You can use nodes to shred your xml in lines, then you can select the correct item with value:
;with x as
(
select cast(employee_xml_string as xml) as employee_xml
from employee_xml
)
SELECT
t.s.value('.', 'nvarchar(max)') AS GovernmentIdentificationNumber
FROM x
CROSS APPLY x.employee_xml.nodes('//Employees/Employee/GovernmentIdentificationNumber') t(s)
Result:
You could have stored xml as XML. Having said that, you can always CAST it:
SELECT employee_xml_xml.value('(/Employees/Employee/GovernmentIdentificationNumber)[1]', 'varchar(100)')
FROM employee_xml
CROSS APPLY (SELECT CAST(employee_xml_string AS xml)) AS x(employee_xml_xml)

Temp Table with XML column in SQL Server

I have a table in SQL Server and I am putting the values of the result set from the table into XML like this:
select
lAccountID,
sName,
sAge
from
AccountDVDetails
where
laccountID = 10
for xml raw ('Values'), ROOT ('Accounts'), ELEMENTS
This query gives me XML like
<Accounts>
<Values>
<lAccountID>10</lAccountID>
<sName>A</sName>
<sAge>21</sAge>
</Values>
<Values>
<lAccountID>10</lAccountID>
<sName>B</sName>
<sAge>22</sAge>
</Values>
<Values>
<lAccountID>10</lAccountID>
<sName>C</sName>
<sAge>23</sAge>
</Values>
</Accounts>
Now I want to store this XML with lAccountId in a temporary table #tmpAccount like
lAccountId XMLValue
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
10 <Accounts><Values><lAccountID>10</lAccountID><sName>A</sName><sAge>21</sAge></Values><Values><lAccountID>10</lAccountID><sName>B</sName><sAge>22</sAge></Values><Values><lAccountID>10</lAccountID><sName>C</sName><sAge>23</sAge></Values></Accounts>
How can I achieve this? I have tried putting the XML into string variable but the XML gets truncated to a certain limit.
Any help will be deeply appreciated. Thanks.
Try this for a nested, hierarchical XML for many Accounts
First I declare some table variables to mock-up a test scenario. I assume, that there is a parent table with accounts:
DECLARE #dummyAccount TABLE(lAccountID INT IDENTITY,SomeData VARCHAR(100));
DECLARE #dummyAccountDetail TABLE(lAccountDetail INT IDENTITY,lAccountID INT,sName VARCHAR(100),sAge INT);--do not store the age as int but the DoB!!!
INSERT INTO #dummyAccount VALUES('Account 1'),('Account 2');
INSERT INTO #dummyAccountDetail VALUES(1,'Jane',20),(1,'John',30)
,(2,'Tim',40),(2,'Tom',50);
The query will list the accounts as first level (I added some descibing attributes just to show the principles, but you can easily let them away. The sub-select will create an XML for each account separately.
SELECT A.lAccountID
,A.SomeData
,(
SELECT D.lAccountID
,D.sName
,D.sAge
FROM #dummyAccountDetail AS D
WHERE D.lAccountID=A.lAccountID
FOR XML PATH('Values'),ROOT('Accounts'),TYPE
)
FROM #dummyAccount AS A
You can easily create the table #tmpAccount just with
SELECT ...
INTO #tmpAccount
FROM ...
...or, if it exists already, just use
INSERT INTO #tmpAccount
SELECT ...
Check This.
select distinct
(
select
lAccountID,
sName,
sAge
from
AccountDVDetails
where
laccountID = 10
for xml raw ('Values'), ROOT ('Accounts'), ELEMENTS
)as XMLValue
,lAccountID into #tmpAccount from AccountDVDetails
where
laccountID = 10
select * from #tmpAccount

How to Copy data from XML Column and Insert it into a Table which Contains column names same as XML Tag Names in MS SQL SERVER

Say If I have Table which contains Single Column of XML datype
Eg:
Details(Column Name in Table)
<emp>--row1 in that column
<Name>Alice</name>
<ID>1</ID>
</emp>
<emp>--row2 in that column
<Name>Bob</name>
<ID>2</ID>
</emp>
Now I need to read this column from the table and insert it on to another table which contains same column names as the XML Tag names i.e
Emp
Name ID
Alice 1
Bob 2
I have tried OPENXML ,XQUERY etc . Nothing Seems to work to read column by column and insert into that row . Can you please guide me on this?
A CROSS APPLY on the xml field with the original table should give you the output you need to insert into the target table.
DECLARE #Source TABLE (XmlData XML)
DECLARE #Emp TABLE (ID INT, Name VARCHAR(15))
INSERT #Source VALUES
('<emp><Name>Alice</Name><ID>1</ID></emp><emp><Name>Bob</Name><ID>2</ID></emp>'),
('<emp><Name>Max</Name><ID>3</ID></emp>')
INSERT #Emp (ID, Name)
SELECT
Employees.Emp.value('ID[1]', 'INT') AS ID,
Employees.Emp.value('Name[1]', 'VARCHAR(25)') AS Name
FROM #Source SRC
CROSS APPLY SRC.XmlData.nodes('/emp') AS Employees(Emp)
SELECT * FROM #Emp
The output from the target table in the example above is below. I added a second record to show how 3 xml "emp" elements across only 2 SQL rows correctly insert 3 target records.
ID Name
----------- ---------------
1 Alice
2 Bob
3 Max
I think you can do this.
declare #str_xml xml --- xml data from your column table
SELECT
[Table].[Column].value('name[1]', 'varchar(100)') as ' Name ',
[Table].[Column].value('ID[1]', 'varchar(20)') as ' ID '
FROM #str_xml.nodes('/ emp') as [Table]([Column])
Note :
name[1] = name on this must be same with tag <name> not <Name>
when you can make output table from xml string you can use it to insert into another table.
http://programcall.com/11/dotnet/how-to-read-data-from-xml-string--and-insert-to-table-sql-server.aspx

Xquery to return rows with restricted nodes

I have a table where a column contains XML data. Now i want to retrieve those xml data with restriction of nodes. Kindly see the following example for more explanation on my scenario,
declare #table table (id int, xmlfield xml) insert into #table select 1,'<Root xmlns="">
<Sample>
<Issue>
<Level>one</Level>
<Descp>First Example</Descp>
</Issue>
<Issue>
<Level>two</Level>
<Descp>Second Example</Descp>
</Issue>
</Sample> </Root>'
select * from #table
Now i need the following result set
Id XMLfield
1 first example
ie, for the selected level,i need the decription for it. More clearly, the node should be restricted for <level>one</level>
(need: What is the description for level one ?)
thanks in advance
Have a look at the xml Data Type Methods
select id,
xmlfield.value('(//Issue[Level = "one"]/Descp/text())[1]', 'varchar(100)') as XMLField
from #table
The XQuery you're looking for is
//Issue[Level = "one"]/Descp/data()