How do I overcome OpenXML's 8000 character limit? - sql

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)

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'.

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

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:

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.

Using XQuery in Sql Server to Parse XML Complex types

I have the following XML :
<Feed>
<FeedId>10</FeedId>
<Component>
<Date>2011-10-01</Date>
<Date>2011-10-02</Date>
</Component>
</Feed>
Now if possible I would like to parse the XML into sql so it's serialized into the following relational data:
FeedId Component_Date
10 2011-10-01
10 2011-10-02
However using the following SQL:
DECLARE #XML XML;
DECLARE #XMLNodes XML;
SET #XML = '<Feed><FeedId>10</FeedId><Component><Date>2011-10-01</Date><Date>2011-10-02</Date></Component></Feed>';
SELECT t.a.query('FeedId').value('.', 'INT') AS FeedId
,t.a.query('Component/Date').value('.', 'VARCHAR(80)') AS [Component_Date]
FROM #XML.nodes(' /Feed') AS t(a)
The closest I get is :
FeedId Component_Date
10 2011-10-012011-10-02
So the date values appear in the same row, is it possible to achieve what I want using XQuery?
You need a second call to .nodes() since you have multiple entries inside your XML - try this:
SELECT
t.a.value('(FeedId)[1]', 'INT') AS FeedId,
c.d.value('(.)[1]', 'DATETIME') AS [Component_Date]
FROM
#XML.nodes('/Feed') AS t(a)
CROSS APPLY
t.a.nodes('Component/Date') AS C(D)
Gives me an output of:
FeedId Component_Date
10 2011-10-01 00:00:00.000
10 2011-10-02 00:00:00.000
OK, I can do it using OPENXML method:
eclare #idoc int
DECLARE #XML XML;
DECLARE #XMLNodes XML;
SET #XML = '<Feed><FeedId>10</FeedId><Component><Date>2011-10-01</Date><Date>2011-10-02</Date></Component></Feed>';
exec sp_xml_preparedocument #idoc OUTPUT, #XML
-- SELECT stmt using OPENXML rowset provider
SELECT *
FROM OPENXML (#idoc, '/Feed/Component/Date',1)
WITH (
FeedId Int '../../FeedId',
ComponentDate Date 'text()'
)

TSQL - use variables in OPENXML

Suppose I have a query like this -
SELECT * FROM
OPENXML(#i, '/root/authors', 2)
WITH authors
Now, I want to pass '/root' via a parameter/variable like -
DECLARE #nodeName varchar(MAX) ----> EDIT: Solution- Use fixed length instead of MAX
SET #nodeName = '/root'
and use #nodeName instead. Then concatenate the rest of the elements dynamically.
I am getting error just by using #nodeName in the OPENXML parameter.
Better to use the new XML type.
create proc [dbo].[getLocationTypes](#locationIds XML,
#typeIds XML=null)
as
begin
set nocount on
SELECT locationId, typeId
FROM xrefLocationTypes
WHERE locationId
IN (SELECT Item.value('.', 'int' )
FROM #locationIDs.nodes('IDList/ID') AS x(Item))
AND (typeId IN
(SELECT Item.value('.', 'int' )
FROM #typeIds.nodes('IDList/ID') AS x(Item)))
ORDER BY 1, 2
end
And then you would call this like:
EXECUTE dbo.getLocationTypes '<IDList><ID>1</ID><ID>3</ID></IDList>',
'<IDList><ID>200</ID><ID>300</ID><ID>400</ID></IDList>'
I tried the following in SQL 2008 R2 and it works fine.
DECLARE #idoc int
DECLARE #doc varchar(1000)
SET #doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
<Order CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00">
<OrderDetail OrderID="10248" ProductID="11" Quantity="12"/>
<OrderDetail OrderID="10248" ProductID="42" Quantity="10"/>
</Order>
</Customer>
<Customer CustomerID="LILAS" ContactName="Carlos Gonzlez">
<Order CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00">
<OrderDetail OrderID="10283" ProductID="72" Quantity="3"/>
</Order>
</Customer>
</ROOT>'
--Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #idoc OUTPUT, #doc
-- Execute a SELECT statement that uses the OPENXML rowset provider.
DECLARE #NodeName VARCHAR(100)
SET #NodeName = '/ROOT/Customer'
SELECT *
FROM OPENXML (#idoc, #NodeName,1)
WITH (CustomerID varchar(10),
ContactName varchar(20))
It could be that other versions of SQL only support the use of NVARCHAR as a parameter, not VARCHAR.
I hope this help.