Importing XML data with a namespace into SQL Server - sql

I have an XML document containing data that I want to import into existing SQL server tables:
<?xml version="1.0" encoding="UTF-8"?>
<geia:GEIA-STD-0007 xmlns:geia="http://www.geia_STD_0007.com/2006/schema" xmlns:xsi=`enter code here`"http://www.w3.org/2001/XMLSchema-instance">
<geia:full_file>
<geia:XA_end_item_acronym_code_data>
<geia:end_item_acronym_code>ON565</geia:end_item_acronym_code>
<geia:logistics_support_analysis_control_number_structure>32222222</geia:logistics_support_analysis_control_number_structure>
</geia:XA_end_item_acronym_code_data>
<geia:XB_logistics_support_analysis_control_number_indentured_item_data>
<geia:end_item_acronym_code>ON565</geia:end_item_acronym_code>
<geia:logistics_support_analysis_control_number>E2C06CAAE</geia:logistics_support_analysis_control_number>
<geia:alternate_logistics_support_analysis_control_number_code>06</geia:alternate_logistics_support_analysis_control_number_code>
<geia:logistics_support_analysis_control_number_type>P</geia:logistics_support_analysis_control_number_type>
<geia:logistics_support_analysis_control_number_nomenclature>CABLE ASSEMBLY W5</geia:logistics_support_analysis_control_number_nomenclature>
<geia:reliability_availability_and_maintainability_indicator>Y</geia:reliability_availability_and_maintainability_indicator>
<geia:system_end_item_identifier>N</geia:system_end_item_identifier>
<geia:technical_manual_functional_group_code>41JE150</geia:technical_manual_functional_group_code>
</geia:XB_logistics_support_analysis_control_number_indentured_item_data>
<geia:XB_logistics_support_analysis_control_number_indentured_item_data>
<geia:end_item_acronym_code>ON565</geia:end_item_acronym_code>
<geia:logistics_support_analysis_control_number>E2C06CAAMZZ</geia:logistics_support_analysis_control_number>
<geia:alternate_logistics_support_analysis_control_number_code>06</geia:alternate_logistics_support_analysis_control_number_code>
<geia:logistics_support_analysis_control_number_type>P</geia:logistics_support_analysis_control_number_type>
<geia:logistics_support_analysis_control_number_nomenclature>CONSUMABLES</geia:logistics_support_analysis_control_number_nomenclature>
<geia:system_end_item_identifier>N</geia:system_end_item_identifier>
</geia:XB_logistics_support_analysis_control_number_indentured_item_data>
</geia:full_file>
</geia:GEIA-STD-0007>
I have been looking online for code that can help me accomplish this task but have not had much luck. So far this is the code I have been trying to use:
----step 1 Import XML data from an XML file into SQL Server table using the OPENROWSET function
drop table lsa.XMLwithOpenXML
CREATE TABLE lsa.XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)
INSERT INTO lsa.XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM OPENROWSET(BULK 'D:\Temp\e2c.xml', SINGLE_CLOB) AS x;
--SELECT * FROM lsa.XMLwithOpenXML
--get xmldata to shred
-------------------------------------------------------------------------
Declare #xmlData as xml
Select #xmlData = XMLData FROM lsa.XMLwithOpenXML
------------------------------------------------------------
--create variable to hold the int id of the xmldoc created by the sp
DECLARE #XMLdocId AS INT
--procedureName, outputId, InputData
EXEC sp_xml_preparedocument #XMLdocId OUTPUT, #xmlData , '<geia:GEIA-STD-0007 xmlns:geia="http://www.geia_STD_0007.com/2006/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
--create an OenXML query to shred the doc, or transfer it into rowsets
INSERT INTO [lsa].[XB]
(
[end_item_acronym_code])
Select end_item_acronym_code from
OpenXML(#XMLdocId, '/geia:XB_logistics_support_analysis_control_number_indentured_item_data',2)
;WITH XMLNAMESPACES ('xmlns:geia="http://www.geia_STD_0007.com/2006/schema' AS geia, DEFAULT 'http://www.w3.org/2001/XMLSchema-instance' )
SELECT
x.c( '.' ) AS result
FROM #xmlData.nodes('geia:GEIA-STD-0007/geia:full_file/geia:XB_logistics_support_analysis_control_number_indentured_item_data') x(c)
EXEC sp_xml_removedocument #XMLdocId
I realize that this code is very wrong. The path that I am passing to the OpenXML() function is wrong, but I have tried many iterations of it and none have been successful. I am also not 100% certain how to go about pulling out the different table data (ie XA, XB) but my plan is to pull from one table then reiterate the code for each additional table. This code will be used to import large amounts of data (I only posted a part of the xml file) with many different tables. If anyone has a better idea, then I would welcome it, as I am still learning.

Related

Creating a query from an XML input parameter in a stored procedure and verifying the output

I have created a stored procedure that reads XML data as its input. I am having two issues that I am hoping someone can help with.
Issue 1: When I execute the stored procedure, I only get back the first value for AccountType (9). I am expecting/wanting to get back all values for AccountType.
Issue 2: Once I have fixed the above issue I would like to use values from AccountType to select users from another table e.g. dbo.UserData
What I have tried:
I saw this on another SO post that you can debug but I am not sure exactly how to use this or what it's doing.
select col.query('.') as Debug
XML:
<root>
<From>4</From>
<AccountType>9</AccountType>
<AccountType>5</AccountType>
<AccountType>6</AccountType>
<AccountType>7</AccountType>
<AccountType>5</AccountType>
<AccountType>4</AccountType>
<AccountType>1</AccountType>
<AccountType>15</AccountType>
<AccountType>16</AccountType>
<AccountType>1</AccountType>
<AccountType>ivs</AccountType>
<AccountType>10</AccountType>
<AccountType>12</AccountType>
<AccountType>11</AccountType>
<AccountType>tfs</AccountType>
<AccountType>vsa</AccountType>
<AccountType>13</AccountType>
<AccountType>14</AccountType>
<GroupID>1</GroupID>
<GroupID>5</GroupID>
</root>
Stored procedure:
CREATE PROCEDURE dbo.UserSelect
#XMLInput XML
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT
'AccountType' = x.v('AccountType[1]', 'nvarchar(2)')
FROM
#XMLInput.nodes('/root') AS x(v)
END
Execution of stored procedure:
DECLARE #XML as XML
SET #XML = '<root>
<From>4</From>
<AccountType>9</AccountType>
<AccountType>5</AccountType>
<AccountType>6</AccountType>
<AccountType>7</AccountType>
<AccountType>5</AccountType>
<AccountType>4</AccountType>
<AccountType>1</AccountType>
<AccountType>15</AccountType>
<AccountType>16</AccountType>
<AccountType>1</AccountType>
<AccountType>ivs</AccountType>
<AccountType>10</AccountType>
<AccountType>12</AccountType>
<AccountType>11</AccountType>
<AccountType>tfs</AccountType>
<AccountType>vsa</AccountType>
<AccountType>13</AccountType>
<AccountType>14</AccountType>
<GroupID>1</GroupID>
<GroupID>5</GroupID>
</root>'
EXEC dbo.UserSelect #XML
You were close, but you needed to specify the 'AccountType' node in the nodes function. And then use the value function to get the value.
select distinct x.v.[value]('.','nvarchar(2)') AccountType
from #XML.nodes('/root/AccountType') x(v)
In an ITVF (Inline Table Valued Function) it looks like:
create function dbo.GetAccountTypeFromXML
(
#Xml xml
)
returns table
return
select distinct x.v.[value]('.','nvarchar(2)') AccountType
from #XML.nodes('/root/AccountType') x(v)
Which can then be used as, for example:
select *
from dbo.UserData
where AccountType in (select AccountType from dbo.GetAccountTypeFromXML(#Xml))

SQL XML Output with PDFs Attached

I have a SQL Server procedure written that exports data in XML format. In the database, I also have PDFs that have been stored as BLOB files that I need to export with the data. Is it possible to convert these to PDF as I export?
This is really easy...
I assume, that the BLOBs live in a table column of type VARBINARY(MAX). Including such a column into a SELECT ... FOR XML PATH will implicitly do the conversion for you.
In this example I use three tiny binary BLOBs, put them into a XML-variable and re-read them. There should be not difference with your PDF BLOBs:
DECLARE #tbl TABLE(ID INT,Content VARBINARY(MAX));
INSERT INTO #tbl VALUES
(1,0x101010101010101010101)
,(2,0x110011001100110011001100)
,(3,0x111000111000111000111000);
DECLARE #xml XML=
(
SELECT ID AS [#ID]
,Content
FROM #tbl
FOR XML PATH('myData'),ROOT('root')
);
SELECT #xml;
The result as XML (implicit conversion to base64)
<root>
<myData ID="1">
<Content>AQEBAQEBAQEBAQE=</Content>
</myData>
<myData ID="2">
<Content>EQARABEAEQARABEA</Content>
</myData>
<myData ID="3">
<Content>ERAAERAAERAAERAA</Content>
</myData>
</root>
Now I read the data from the XML
SELECT B.value('Content[1]','varbinary(max)') AS BackToVarbinary
FROM #xml.nodes('/root/myData') AS A(B)
The result
BackToVarbinary
0x0101010101010101010101
0x110011001100110011001100
0x111000111000111000111000

how to get values inside an xml column, when it's of type nvarchar

My question is similar to this one: Choose a XML node in SQL Server based on max value of a child element
except that my column is NOT of type XML, it's of type nvarchar(max).
I want to extract the XML node values from a column that looks like this:
<Data>
<el1>1234</el1>
<el2>Something</el2>
</Data>
How can I extract the values '1234' and 'Something' ?
doing a convert and using the col.nodes is not working.
CONVERT(XML, table1.col1).value('(/Data/el1)[1]','int') as 'xcol1',
After that, I would like to do a compare value of el1 (1234) with another column, and update update el1 as is. Right now I'm trying to just rebuild the XML when passing the update:
ie
Update table set col1 ='<Data><el1>'+#col2+'</el1><el2>???</el2>
You've got to tell SQL Server the number of the node you're after, like:
(/Data/el1)[1]
^^^
Full example:
declare #t table (id int, col1 varchar(max))
insert #t values (1, '<Data><el1>1234</el1><el2>Something</el2></Data>')
select CAST(col1 as xml).value('(/Data/el1)[1]', 'int')
from #t
-->
1234
SQL Server provides a modify function to change XML columns. But I think you can only use it on columns with the xml type. Here's an example:
declare #q table (id int, col1 xml)
insert #q values (1, '<Data><el1>1234</el1><el2>Something</el2></Data>')
update #q
set col1.modify('replace value of (/Data/el1/text())[1] with "5678"')
select *
from #q
-->
<Data><el1>5678</el1><el2>Something</el2></Data>
At the end of the day, SQL Server's XML support makes simple things very hard. If you value maintainability, you're better off processing XML on the client side.

Serializing Hashset contents to a SQL table

I have a hashset that I want to serialize to a SQL Server table. When serialized hashset looks like this...
<InstallerContactIds>
<int>153771</int>
<int>209572</int>
</InstallerContactIds>
I am using the following to insert the XML into the table...
INSERT INTO dbo.cv_AssessorActionPlanInstallers
SELECT #AssessorActionPlanId, InstallerId
From OPENXML (#XmlDocumentHandle, 'AssessorActionPlan/InstallerContactIds', 2)
With
(
InstallerId int 'int'
)
However, I only get the first id inserted into the table. Is it possible to insert all ids in this case?
I am using SQL Server 2005
You didn't specify what version of SQL you are using, but if you are on 2005 or newer, you can use the new XML data type.
declare #xml xml
select #xml = '
<InstallerContactIds>
<int>153771</int>
<int>209572</int>
</InstallerContactIds>'
select
x.i.value('.', 'int')
from
#xml.nodes('/InstallerContactIds/int') as x(i)
If you are stuck using OpenXML, it should work if you do this:
INSERT INTO dbo.cv_AssessorActionPlanInstallers
SELECT #AssessorActionPlanId, InstallerId
From OPENXML (#XmlDocumentHandle, 'AssessorActionPlan/InstallerContactIds/int', 2)
With
(
InstallerId int '.'
)

Parse and Import XML into Table in SQL Server

I've written a CLR assembly that exports a table's data to an XML file. Now I want to import this data into a temp table on another instance.
The XML file structure is like this:
<row>
<SystemInformationID>1</SystemInformationID>
<Database_x0020_Version>10.00.80404.00</Database_x0020_Version>
<VersionDate>2008-04-04T00:00:00</VersionDate>
<ModifiedDate>2008-04-04T00:00:00</ModifiedDate>
</row>
I want the XML to be parsed in the destination location and imported into a temp table. I have the main table there too, so I can get the table structure from there.
Is there a way? I use OPENXML but it seems not to be working correctly. I can read the XML file into a table, which will be stored in a column with XML data type. My problem is parsing the data in that column.
This is a temp attempt:
CREATE TABLE ##T (IntCol int, XmlCol xml)
GO
INSERT INTO ##T(XmlCol)
SELECT * FROM OPENROWSET(
BULK 'c:\HISOutput.xml',
SINGLE_CLOB) AS x
--works correctly up to this point
DECLARE #x xml
DECLARE #id int
SELECT #x=XmlCol FROM ##T
EXEC sp_xml_preparedocument #id OUTPUT, #x
SELECT *
FROM OPENXML (#id,'/row',2)
WITH
dbo.awbuildversion
--I used dbo.awbuildversion table from AdventureWorks DB for testing
this doesn't show the first column no matter how I change the OPENXML instruction.
tx in advance
I'm not quite sure what you want, because your comment to OMG Ponies' answer is different to your question. What is the problem with temp table/table structure?
Anyway, I wouldn't use OPENXML or sp_xml_preparedocument on SQL Server 2050 and above (which you have I assume because you mentioned CLR) because of the memory leak risk.
Also, if you need the table stucture then you could use INTO #tempTable
DECLARE #foo xml
SET #foo = '<row>
<SystemInformationID>1</SystemInformationID>
<Database_x0020_Version>10.00.80404.00</Database_x0020_Version>
<VersionDate>2008-04-04T00:00:00</VersionDate>
<ModifiedDate>2008-04-04T00:00:00</ModifiedDate>
</row>'
SELECT
bar.value('./SystemInformationID[1]','INT') AS 'SystemInformationID',
bar.value('./Database_x0020_Version[1]','VARCHAR(14)') AS 'Database_x0020_Version',
bar.value('./VersionDate[1]','DATETIME') AS 'VersionDate',
bar.value('./ModifiedDate[1]','DATETIME') AS 'ModifiedDate'
INTO #tempTable -- This?
FROM
#foo.nodes('/row') AS foo(bar) --use nodes not OPENXML