Import XML with Attribute to SQL Server Table - sql-server

I can't get the value for the XML attribute 'Country' into my table.
What am I doing wrong?
Here is my XML:
<?xml version="1.0" encoding="utf-8"?>
<CustomerDetails>
<PersonalInfo Country="USA">
<CustID>1001</CustID>
<CustLastName>Smith</CustLastName>
<DOB>2011-05-05T09:25:48.253</DOB>
<Address>
<Addr1>100 Smith St.</Addr1>
<City>New York</City>
</Address>
</PersonalInfo>
</CustomerDetails>
Here is my SQL:
Drop table #Cust
CREATE TABLE #Cust
(CustID INT, CustLastName VARCHAR(10)
, DOB DATETIME, Addr1 VARCHAR(100), City VARCHAR(10), Country VARCHAR(20))
insert into #Cust
select
c3.value('CustID[1]','int'),
c3.value('CustLastName[1]','varchar(10)'),
c3.value('DOB[1]','DATETIME'),
c3.value('(Address/Addr1)[1]','VARCHAR(100)'),
c3.value('(Address/City)[1]','VARCHAR(10)'),
c3.value('Country[1]','VARCHAR(20)')
from
(
select
cast(c1 as xml)
from
OPENROWSET (BULK 'C:\Users\wattronts\Documents\XMLImportTest.xml',SINGLE_BLOB) as T1(c1)
)as T2(c2)
cross apply c2.nodes('/CustomerDetails/PersonalInfo') T3(c3)
Select * from #Cust
Thanks for your help.

Use # to specify that you want an attribute.
T3.c3.value('#Country', 'varchar(50)')

Related

How to select all children from XML in Sql Server?

I have the below XML when I run the select query it considers only the first value, what I am missing here?
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>1</string>
<string>2</string>
<string>3</string>
.............
</ArrayOfString>
Below query only returns 1, I am expecting it to return all values like 1,2,3...
SELECT xmlu.v1.value('string[1]', 'BIGINT')
FROM
#xml.nodes('/ArrayOfString')
AS xmlU(v1)
If you want one row per string node, you need to include the string node in your nodes clause:
SELECT AOS.s.value('(./text())[1]','bigint') AS string --If it's string, why are you asking for a bigint?
FROM (VALUES(#XML))V(X)
CROSS APPLY V.X.nodes('/ArrayOfString/string')AOS(s);
It seems that you are looking for something like the following.
It is better not to use the IN clause because it usually gets converted to inefficient OR expressiions.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, city VARCHAR(20));
INSERT INTO #tbl (city) VALUES
('Miami'),
('Orlando'),
('Dallas'),
('New York'),
('Hollywood');
DECLARE #parameter XML =
N'<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>1</string>
<string>2</string>
<string>3</string>
</ArrayOfString>'
-- DDL and sample data population, end
;WITH rs AS
(
SELECT c.value('.', 'INT') AS ID
FROM #parameter.nodes('/ArrayOfString/string/text()') AS t(c)
)
SELECT *
FROM #tbl AS t INNER JOIN
rs ON t.ID = rs.ID;

SQL Cross Apply no results

I have ugly XML that looks like this:
<?xml version="1.0"?>
<MainTag xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RecordID="201801026543210">
<Field Name="TheFieldName">
<FieldValue>Field Contents</FieldValue>
<ListTag>
<ListItem>
<Value>This List Value</Value>
<Source>source.txt</Source>
<ListType>text</ListType>
<ItemNumber>6912</ItemNumber>
<MoreData>some text here</MoreData>
<Address>address data</Address>
<Ranking>102</Ranking>
</ListItem>
<ListItem>
<Value>Another List Value</Value>
<Source>other.txt</Source>
<ListType>text</ListType>
<ItemNumber>7919</ItemNumber>
<MoreData>more text here</MoreData>
<Address>address data</Address>
<Ranking>41</Ranking>
</ListItem>
</ListTag>
</Field>
</MainTag>
What I want is query results that gives me a spreadsheet, essentially:
RecordID FieldName FieldValue ListValue ListSource ListType ListItemNumber …
201801026543210 TheFieldName Field Contents This List Value source.txt text 6912
201801026543210 TheFieldName Field Contents Another List Value other.txt text 7919
To aid in the fun, the XML is stored in a varchar field, not an XML field.
As example data and queries I've tried:
DECLARE #Tbl TABLE (
TblID varchar(15)
, Fld varchar(max)
)
INSERT INTO #Tbl SELECT '201801026543210', '<?xml version="1.0"?><MainTag xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RecordID="201801026543210"><Field Name="TheFieldName"><FieldValue>Field Contents</FieldValue><ListTag><ListItem><Value>This List Value</Value><Source>source.txt</Source><ListType>text</ListType><ItemNumber>6912</ItemNumber><MoreData>some text here</MoreData><Address>address data</Address><Ranking>102</Ranking></ListItem><ListItem><Value>Another List Value</Value><Source>other.txt</Source><ListType>text</ListType><ItemNumber>7919</ItemNumber><MoreData>more text here</MoreData><Address>address data</Address><Ranking>41</Ranking></ListItem></ListTag></Field></MainTag>'
-- this shows that i am reading the main tag
SELECT t.r.value('#RecordID','varchar(15)') AS RecordID
, t.r.query('.') as fullvalue
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM #Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
-- and this works to read the attribute from the first field
SELECT t.r.value('#RecordID', 'varchar(18)') AS RecordID
, f.r.value('#Name', 'varchar(100)') AS Field
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM #Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
CROSS APPLY Fld.nodes('/MainTag/Field') AS f(r)
-- this does NOT work to read the second field
SELECT t.r.value('#RecordID','varchar(18)') AS RecordID
, f.r.value('.', 'varchar(100)') AS ValueF
, p.r.query('.') AS QueryP
, p.r.value('.', 'varchar(100)') AS ValueP
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM #Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
CROSS APPLY Fld.nodes('/MainTag/Field') AS f(r)
CROSS APPLY Fld.nodes('/MainTag/FieldValue') AS p(r)
-- i honestly feel like this should be using nodes off of the parent nodes method
-- , but this is NOT working either
SELECT t.r.value('#RecordID','varchar(18)') AS RecordID
, p.r.query('.') AS FieldValue
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM #Tbl
) AS s
CROSS APPLY s.Fld.nodes('/MainTag') AS t(r)
CROSS APPLY t.r.nodes('/MainTag/FieldValue') AS p(r)
I've seen some other questions/samples that grab just the first entry. I do not want that. I want a big blob of data. I want the unique fields to repeat for each "ListItem". To say that another way: I know this is akin to a one-to-many join where the fields in the "one" table will repeat for each row in the "many" table.
Technically, in my data there may be more than one "Field" as well.
There is only one FieldValue for that field.
There is one or more ListItems.
Try it with this query:
SELECT s.Fld.value('(/MainTag/#RecordID)[1]','bigint') AS RecordID
,A.f.value('#Name','nvarchar(max)') as FieldName
,A.f.value('(FieldValue/text())[1]','nvarchar(max)') as FieldValue
,B.li.value('(Value/text())[1]','nvarchar(max)') as ListValue
,B.li.value('(Source/text())[1]','nvarchar(max)') as ListSource
--and so on
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM #Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag/Field') AS A(f)
CROSS APPLY A.f.nodes('ListTag/ListItem') AS B(li)
Hint
If there is any chance to change storage from VARCHAR to XML it's worth it...

Insert XML in SQL Server

Good afternoon all.
Currently, I have make a small demo with XML in SQl Server.
I have table with name: tb_xml_demo(ID, Name, Descr)
And each time when I insert to this table. ID column like this:
001, 002, 003 ....
This is my procedure
alter proc sp_xml_demo_cud
#p_xml xml
as
begin
declare #dochandle int;
exec sp_xml_preparedocument #dochandle output,#p_xml;
insert into tb_xml_demo(id, name, descr)
select
(select
format(isnull(convert(int, max(id)), 0) + 1, '000')
from tb_xml_demo) id,
name,
descr
from
OPENXML(#dochandle,'/root/item',2)
with
(name nvarchar(50),
descr nvarchar(50),
crud varchar(1)
)
end;
And this is my xml:
exec sp_xml_demo_cud
'<root>
<item>
<name>9876543</name>
<descr>1sdfsd</descr>
</item>
<item>
<name>333</name>
<descr>333</descr>
</item>
</root>';
And this is result after executing the procedure:
id Name Descr
001 9876543 1sdfsd
001 333 333
Please help me.
Thanks a lot.
I would recommend doing this:
create your table with a ID INT IDENTITY(1,1) column to let SQL Server handle the generation of unique ID values
add a computed column (I called it PaddedID) that uses the system-generated, valid ID to display with leading zeroes
parse the XML with the built-in, native XQuery functionality (instead of the legacy OPENXML stuff which is notorious for memory leaks)
This gives me this code:
-- create your table
CREATE TABLE tb_xml_demo
(ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
PaddedID AS RIGHT('0000' + CAST(ID AS VARCHAR(4)), 4) PERSISTED,
Name VARCHAR(50),
Descr VARCHAR(100)
)
-- declare your INPUT XML document
DECLARE #input XML = '<root>
<item>
<name>9876543</name>
<descr>1sdfsd</descr>
</item>
<item>
<name>333</name>
<descr>333</descr>
</item>
</root>'
-- parse the XML using XQuery and insert the results into that newly created table
INSERT INTO dbo.tb_xml_demo
(Name, Descr)
SELECT
ItemName = xc.value('(name)[1]', 'varchar(50)'),
ItemDescr = xc.value('(descr)[1]', 'varchar(100)')
FROM
#input.nodes('/root/item') AS XT(XC)
-- select the values from the table
SELECT * FROM dbo.tb_xml_demo
and this results in an output of:

XML Parsing & T-SQL

Given the following from an XML field in a table:
<View>
<Criminal xmlns="http://tempuri.org/crimes.xsd">
<Person>
<PersonID>1234</PersonID>
<LastName>SMITH</LastName>
<FirstName>KEVIN</FirstName>
<Cases>
<PersonID>1234</PersonID>
<CaseNumber>12CASE34</CaseNumber>
</Cases>
</Person>
</Criminal>
</View>
How would I pull the Person/PersonID, LastName, Firstname info? Same goes for the CaseNumber.
My next issue is similar to above but lets add a second namespace:
<MessageContent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Content>Content in here!!</Content>
<Type>Empty</Type>
</MessageContent>
Notice I have 2 namespaces in there AND they also have ":xsi" and ":xsd" in there too. I think those are referred to as schemas.
Try this:
DECLARE #table TABLE (ID INT NOT NULL, XmlContent XML)
INSERT INTO #table VALUES(1, '<View>
<Criminal xmlns="http://tempuri.org/crimes.xsd">
<Person>
<PersonID>1234</PersonID>
<LastName>SMITH</LastName>
<FirstName>KEVIN</FirstName>
<Cases>
<PersonID>1234</PersonID>
<CaseNumber>12CASE34</CaseNumber>
</Cases>
</Person>
</Criminal>
</View>')
;WITH XMLNAMESPACES('http://tempuri.org/crimes.xsd' AS ns)
SELECT
PersonID = XmlContent.value('(/View/ns:Criminal/ns:Person/ns:PersonID)[1]', 'int'),
FirstName = XmlContent.value('(/View/ns:Criminal/ns:Person/ns:FirstName)[1]', 'varchar(50)'),
LastName = XmlContent.value('(/View/ns:Criminal/ns:Person/ns:LastName)[1]', 'varchar(50)')
FROM #table
WHERE ID = 1
Returns an output of:
And for your second part of the question: yes, you have two namespaces defined - but they're not being used at all - so you can basically just ignore them:
INSERT INTO #table VALUES(2, '<MessageContent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Content>Content in here!!</Content>
<Type>Empty</Type>
</MessageContent>')
SELECT
Content = XmlContent.value('(/MessageContent/Content)[1]', 'varchar(50)'),
Type = XmlContent.value('(/MessageContent/Type)[1]', 'varchar(50)')
FROM #table
WHERE ID = 2
Returns:

Puzzling xml select syntax in Sql Server

In the below sql code, what does T(C) mean? What is T and what is C?
declare #employeeData xml --this would be your XML input parameter
set #employeeData = '<employeeData>
<employee LastName="Smith" FirstName="Randolph" EmployeeID="1234567"/>
</employeeData>'
declare #xmlTable table (LastName nvarchar(255), FirstName nvarchar(255), EmployeeID int)
insert into #xmlTable (LastName, FirstName, EmployeeID)
select
C.value('#LastName','nvarchar(255)') as LastName,
C.value('#FirstName','nvarchar(255)') as FirstName,
C.value('#EmployeeID','int') as EmployeeID
from
#employeeData.nodes('/employeeData/employee') T(C)
select * from #xmlTable
Check MSDN: http://msdn.microsoft.com/en-us/library/ms188282.aspx
T - Table
C - Column

Resources