getting NULL in sql table while parsing xml in SQL Server 2008 - sql

I'm trying to parse an XML document with a query.
Here is a sample of my XML:
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://bbhgtm.gov.com/oos/export/1" xmlns:oos="http://bbhgtm.gov.com/oos/types/1">
<notificationOK>
<oos:id>8373125</oos:id>
<oos:notificationNumber>0173200001513000422</oos:notificationNumber>
Here is my query
declare #hdoc int
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x,
'
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:q="http://bbhgtm.gov.com/oos/export/1"
xmlns:oos="http://bbhgtm.gov.com/oos/types/1"/>
'
select *
from openxml(#hdoc, '/notificationOK/oos:id/oos:notificationNumber/', 1)
WITH(
versionNumber int 'oos:versionNumber'
,createDate datetime 'oos:createDate'
)
EXEC sp_xml_removedocument #hdoc
But I'm getting NULL in my SQL table.
What to do?

You're ignoring the XML namespaces on your XML document!
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://bbhgtm.gov.com/oos/export/1"
xmlns:oos="http://bbhgtm.gov.com/oos/types/1">
See those xmlns=..... and xmlns:oos=...... attributes? Those define XML namespaces that need to be taken into account when querying!
Also, I'd recommend to use the built-in, native XQuery support rather than the clumsy OPENXML code.
Try this code here:
DECLARE #input XML =
'<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://bbhgtm.gov.com/oos/export/1"
xmlns:oos="http://bbhgtm.gov.com/oos/types/1">
<notificationOK>
<oos:id>8373125</oos:id>
<oos:notificationNumber>0173200001513000422</oos:notificationNumber>
</notificationOK>
</export>'
;WITH XMLNAMESPACES('http://bbhgtm.gov.com/oos/types/1' AS oos,
DEFAULT 'http://bbhgtm.gov.com/oos/export/1')
SELECT
id = XC.value('(oos:id)[1]', 'int'),
NotificationNumber = XC.value('(oos:notificationNumber)[1]', 'bigint')
FROM
#input.nodes('/export/notificationOK') AS XT(XC)
This results in an output something like this:

Related

Insert XML file into SQL Server

I'm trying to import an XML file into a SQL table. I found a few examples of code to do this, but I can't seem to get it to work. I've tried a few variations in my code but at this point I'm not sure if the issue is the XML file structure or my SQL.
Below is the code I'm using as well as the XML file (truncated to one record).
CREATE TABLE workspace.dbo.tbt_SED_XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)
INSERT INTO workspace.dbo.tbt_SED_XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM OPENROWSET(BULK 'File.xml', SINGLE_BLOB) AS x;
DECLARE #XML AS XML, #hDoc AS INT, #SQL NVARCHAR (MAX)
SELECT #XML = XMLData FROM workspace.dbo.tbt_SED_XMLwithOpenXML WHERE ID = '1' -- The row to process
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML
INSERT INTO workspace.dbo.tb_SED_Emails
SELECT email
FROM OPENXML(#hDoc, 'responseData/manifest/contact_data')
WITH
(
email [varchar](128) 'email'
)
EXEC sp_xml_removedocument #hDoc
GO
XML File Example:
<?xml version="1.0" encoding="utf-8"?>
<methodResponse>
<item>
<methodName>
<![CDATA[]]>
</methodName>
<responseData>
<manifest>
<contact_data>
<email>jason.kang#stanfordalumni.org</email>
</contact_data>
</manifest>
</responseData>
<responseNum>
<![CDATA[1]]>
</responseNum>
<responseCode>
<![CDATA[]]>
</responseCode>
</item>
</methodResponse>
Try to use the built-in, native XQuery support instead of the clunky old OPENXML stuff:
SELECT
Email = XC.value('(email)[1]', 'varchar(255)')
FROM
workspace.dbo.tbt_SED_XMLwithOpenXML
CROSS APPLY
XMLData.nodes('/methodResponse/item/responseData/manifest/contact_data') AS XT(XC)
That should output the desired e-mail address for you:
You are using the wrong xPath expression.
Change 'responseData/manifest/contact_data' to 'methodResponse/item/responseData/manifest/contact_data'.

OpenXML Import XML file to SQL server table

I am trying to set up an SQL job to import an XML file into an SQL Server table. Using OPENXML, I can't seem to select the specific data I need from the file. Here's my code and XML data. I am trying to select Facility and Entity_Code but when I run the code, these fields appear as blank.
I would like to transfer these fields into their own table.
Thanks in advance.
Declare #x xml
select #x=p
from OPENROWSET(Bulk'\\vmirsdh01\fast_data\Small.xml', SINGLE_BLOB) as T(P)
Select #x
Declare #hdoc int
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x
Select *
FROM OPENXML (#hdoc,'/Report/Tablix1/Details_Collection/Details',0)
with(Facility nvarchar(255) '#Facility',
Entity_Code nvarchar(255) '#Entity_Code')
exec sp_xml_removedocument #hdoc
'************ XML
<?xml version="1.0" encoding="utf-8"?><Report xsi:schemaLocation="T-Report https://csre.xxx.com%2FDevelopment%20Folder%2FIand%2FT-Report&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID=4keav12uayp33ve3uczpgmfr&rc %3ASchema=True" Name="T-Report" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="T_Report">
<Tablix1>
<Details_Collection><Details Facility="Fxx" Tool_Type="Base Build" Entity_Code="EquiP1" /></Details_Collection>
</Tablix1>
</Report>
Here is an executable version
Declare #x xml
select #x='<?xml version="1.0" encoding="utf-8"?><Report xsi:schemaLocation="T-Report https://csre.xxx.com%2FDevelopment%20Folder%2FIand%2FT-Report&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID=4keav12uayp33ve3uczpgmfr&rc %3ASchema=True" Name="T-Report" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="T_Report">
<Tablix1>
<Details_Collection><Details Facility="Fxx" Tool_Type="Base Build" Entity_Code="EquiP1" /></Details_Collection>
</Tablix1>
</Report>'
Declare #hdoc int
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x
Select *
FROM OPENXML (#hdoc,'/Report/Tablix1/Details_Collection/Details',0)
with(Facility nvarchar(255) '#Facility',
Entity_Code nvarchar(255) '#Entity_Code')
exec sp_xml_removedocument #hdoc
You have a default namespace that you need to take into consideration xmlns="T_Report".
Using the XML variable directly your query would look like
with xmlnamespaces(default 'T_Report')
select D.X.value('#Facility', 'nvarchar(255)'),
D.X.value('#Entity_Code', 'nvarchar(255)')
from #x.nodes('/Report/Tablix1/Details_Collection/Details') as D(X)
If you for some reason want to use openxml you need to declare the namespace in the third parameter to sp_xml_preparedocument.
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x, '<root xmlns:xx="T_Report"/>'
Select *
FROM OPENXML (#hdoc,'/xx:Report/xx:Tablix1/xx:Details_Collection/xx:Details',0)
with(Facility nvarchar(255) '#Facility',
Entity_Code nvarchar(255) '#Entity_Code')
exec sp_xml_removedocument #hdoc
Your XML has an opening tag of <Report> but your query is for an opening tag called <Result>.
While I can't swear that everything will work after you fix that (I don't do much with OPENXML) I'm fairly confident that that is a problem.

how to select this xml in sql server 2008

I need to select all guid node in the xml. but the code below only select the first one of them. how to do it?
DECLARE #doc XML
SET #doc =
'<ArrayOfGuid xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<guid>96eecbe2-d645-465d-8232-c7f21e3c6bf8</guid>
<guid>38985702-0c0b-4e9c-bccb-af84ba4dd7ff</guid>
<guid>67852205-092e-4db8-b31e-6f5d457db294</guid>
<guid>92cf9106-445f-4b01-8259-613596b8a2a7</guid>
</ArrayOfGuid>'
DECLARE #docHandle INT
EXEC sp_xml_preparedocument #docHandle OUTPUT,
#doc
SELECT [guid]
FROM OPENXML(#docHandle, '/ArrayOfGuid', 2)
WITH
([guid] UNIQUEIDENTIFIER)
the result is just one row: 96EECBE2-D645-465D-8232-C7F21E3C6BF8
I need all 4 rows.
There are probably better ways to do this, but here's one of them:
SELECT text as guid
FROM OPENXML(#docHandle, '//ArrayOfGuid/guid/text()', 2)
You can also use this approach using the native XQuery capabilities in SQL Server 2005 and newer:
SELECT
Guids.value('(.)[1]', 'uniqueidentifier')
FROM
#doc.nodes('/ArrayOfGuid/guid') AS XTbl(Guids)
I always prefer this method over the older OPENQUERY approach

Bulk Import XML into SQL Server

I was looking at these examples on Microsoft.com here:
http://support.microsoft.com/kb/316005
http://msdn.microsoft.com/en-us/library/aa225754%28v=sql.80%29.aspx
But it's saying in part of it's steps that VBScript code has to be executed, and I wasn't able to find where the VBScript should be executed. Is it possible to be executed in SQL Server itself?
The code from the site looks something like this:
Set objBL = CreateObject("SQLXMLBulkLoad.SQLXMLBulkLoad")
objBL.ConnectionString = "provider=SQLOLEDB.1;data source=MySQLServer;
database=MyDatabase;uid=MyAccount;pwd=MyPassword"
objBL.ErrorLogFile = "c:\error.log"
objBL.Execute "c:\customermapping.xml", "c:\customers.xml"
Set objBL = Nothing
This looks like it could be executed in classic asp or something, but I prefer to keep it inside SQL Server. Does anyone know how to execute something like this all with-in SQL Server? or does anyone have a better method for Bulk import XML into SQL server?
SQL Server is capable of reading XML and inserting it as you need. Here is an example of an XML file and insertion pulled from here:
XML:
<Products>
<Product>
<SKU>1</SKU>
<Desc>Book</Desc>
</Product>
<Product>
<SKU>2</SKU>
<Desc>DVD</Desc>
</Product>
<Product>
<SKU>3</SKU>
<Desc>Video</Desc>
</Product>
</Products>
Insert statement that is parsing the XML:
INSERT INTO Products (sku, product_desc)
SELECT X.product.query('SKU').value('.', 'INT'),
X.product.query('Desc').value('.', 'VARCHAR(30)')
FROM (
SELECT CAST(x AS XML)
FROM OPENROWSET(
BULK 'C:\Products.xml',
SINGLE_BLOB) AS T(x)
) AS T(x)
CROSS APPLY x.nodes('Products/Product') AS X(product);
I tried this and for 975 rows from a 1MB XML file, this took about 2.5 minutes to execute on a very fast PC.
I switched to using OpenXml in a multi-step process and process takes less than a second.
CREATE TABLE XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)
INSERT INTO XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM OPENROWSET(BULK 'clients.xml', SINGLE_BLOB) AS x;
DECLARE #XML AS XML, #hDoc AS INT, #SQL NVARCHAR (MAX)
SELECT #XML = XMLData FROM XMLwithOpenXML WHERE ID = '1' -- The row to process
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML
INSERT INTO Clients
SELECT CustomerID, CustomerName
FROM OPENXML(#hDoc, 'Clients/Client')
WITH
(
CustomerID [varchar](50) 'ID',
CustomerName [varchar](100) 'Name'
)
EXEC sp_xml_removedocument #hDoc
GO
I got this from here:
http://www.mssqltips.com/sqlservertip/2899/importing-and-processing-data-from-xml-files-into-sql-server-tables/
Basically you load the XML into a table as a big blob of text, then you use OpenXml to process it.

How do I overcome OpenXML's 8000 character limit?

I'm loading an XML in SQL using OpenXML while declaring the variable the max i can go up to is 8000 chars :
DECLARE #xml_text varchar(8000)
Since text, ntext is not allowed to be used with openXML what other alternatives do i have to load the entire XML (over 20000 chars) in SQL ?
You should be able to use varchar(max) (SQL 2005 and higher)
DECLARE #idoc int
DECLARE #doc varchar(max)
SET #doc = '
<myxml>
<node nodeid="1" nodevalue="value 1">
</node>
</myxml>'
EXEC sp_xml_preparedocument #idoc OUTPUT, #doc
SELECT
*
FROM
OPENXML (#idoc, '/myxml/node',1) WITH ( nodeid varchar(10), nodevalue varchar(20) )
If you're using SQL 2005 or better you could use the XML data type itself. This way you would be able to avoid using OPENXML:
DECLARE #XDoc XML
SET #XDoc = '<Customer>
<FirstName>Fred</FirstName>
<LastName>Flinstone</LastName>
</Customer>
<Customer>
<FirstName>Barney</FirstName>
<LastName>Rubble</LastName>
</Customer>'
SELECT
Tbl.Col.value('FirstName[1]', 'VARCHAR(MAX)'),
Tbl.Col.value('LastName[1]', 'VARCHAR(MAX)')
FROM #XDoc.nodes('/Customer') Tbl(Col)