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.
Related
I'm trying to import an XML file into a SQL cell to process it. My first idea is do an OPENROWSET to keep the XML and the just divide it with NODES. One of the XML its too huge to keep it on a CELL, so the OPENROWSET cut the XML, so It's impossible to work with it then. That is the code:
DECLARE #XMLwithOpenXML TABLE
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)
INSERT INTO #XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn
,GETDATE()
FROM OPENROWSET(BULK 'C:\temp\PP015.xml', SINGLE_CLOB) AS x;
SELECT * FROM #XMLwithOpenXML
The second option is use the BCP to do the same, but I'm getting an error.
DECLARE #sql NVARCHAR(500)
SET #sql = 'bcp [ExternaDB].[dbo].[xmltab] IN "C:\temp\PP015.xml" -T -c'
EXEC xp_cmdshell #sql
select * from xmltab
I want to know if I'm on the correct way (How to work with an XML when is already in an SQL cell I know how to do it) and how I can BULK import the full XML into a cell without Length constraint.
What is the size of the XML file on the file system?
Please try the following solution. It is very similar to yours with three differences:
SINGLE_BLOB instead of SINGLE_CLOB
No need in CONVERT(XML, BulkColumn)
DEFAULT clause is used for the LoadedDateTime column
Additionally, you can use SSIS for the task. SSIS has a streaming XML Source Adapter with no XML file size limitation.
SQL
DECLARE #tbl TABLE(
ID INT IDENTITY PRIMARY KEY,
XmlData XML,
LoadedDateTime DATETIME DEFAULT (GETDATE())
);
INSERT INTO #tbl(XmlData)
SELECT BulkColumn
FROM OPENROWSET(BULK N'C:\temp\PP015.xml', SINGLE_BLOB) AS x;
SELECT * FROM #tbl;
Thanks for the help but I found the solution. SQL has configurate a maxium characters retrieved for XML data. To solve this issue just we have to reconfigure this parameter.
enter image description here
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'.
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:
I have a xml column that look like
SET #XMLData = '<ArrayOfEntityNested xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.Bijak">
<EntityNested>
<Id xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto">1</Id>
<Date xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak">0001-01-01T00:00:00</Date>
<Description xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak">deesc</Description>
<Number xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak" i:nil="true" />
</EntityNested>
</ArrayOfEntityNested>'
I need insert data from the XML into a temp table.
here
For this I use from following code. But it's not working, and it's not inserting any data into temp table.
--Variables Decleration
DECLARE #XMLData VARCHAR(MAX)
DECLARE #idoc INT
-- Creating Temporary Table
CREATE TABLE #TEMP_TABLE
(
REC_ID INT IDENTITY(1,1),
[Id] INT,
[Date] VARCHAR(50),
[Number] VARCHAR(50),
);
--Case 1
SET #XMLData = '<ArrayOfEntityNested xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.Bijak">
<EntityNested>
<Id xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto">1</Id>
<Date xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak">0001-01-01T00:00:00</Date>
<Number xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak" i:nil="true" />
</EntityNested>
</ArrayOfEntityNested>
'
--Reading Data from XML and inserting into Temp Table
EXECUTE sp_xml_preparedocument #idoc OUTPUT, #XMLData
INSERT INTO #TEMP_TABLE
SELECT *
FROM OpenXML(#idoc,'/ArrayOfEntityNested/EntityNested', 1)
WITH #TEMP_TABLE
EXECUTE sp_xml_removedocument #idoc
--Displaying data from Temp Table
SELECT * FROM #TEMP_TABLE
DROP TABLE #TEMP_TABLE;
But that doesn't work, if xml format correct might look like :
SET #XMLData = '<ArrayOfEntityNested>
<EntityNested>
<Id>1</Id>
<Date>0001-01-01T00:00:00</Date>
<Description>deesc</Description>
<EmployeeId>2</EmployeeId>
<IsDeleted>false</IsDeleted>
<LoadingPermitTruckId>7541</LoadingPermitTruckId>
</EntityNested>
</ArrayOfEntityNested>'
then it works.
Please help me.
First of all - please use appropriate data types! If your source data is XML - why aren't you using the XML datatype?
Also, if you have a Date in your table - why isn't that a DATE or DATETIME type?? And why is the Number a VARCHAR(50) ??
Makes no sense......
Then: you're not looking at the XML namespaces that are present in the XML document - but you must!
At lastly - I would recommend using the native XQuery support instead of the legacy, deprecated sp_xml_preparedocument / OpenXML approach....
Seems much easier, much clearer to me...
Use this:
-- variable declaration
DECLARE #XMLData XML
-- creating temporary table
CREATE TABLE #TEMP_TABLE
(
REC_ID INT IDENTITY(1,1),
[Id] INT,
[Date] DATETIME2(3),
[Number] INT
);
and then use proper XQuery statements, including the XML namespaces to handle the data:
SET #XMLData = '<ArrayOfEntityNested xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.Bijak">
<EntityNested>
<Id xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto">1</Id>
<Date xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak">0001-01-01T00:00:00</Date>
<Number xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak" i:nil="true" />
</EntityNested>
<EntityNested>
<Id xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto">42</Id>
<Date xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak">2013-12-22T14:45:00</Date>
<Number xmlns="http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak">373</Number>
</EntityNested>
</ArrayOfEntityNested>'
;WITH XMLNAMESPACES ('http://schemas.datacontract.org/2004/07/Gbms.Dto.Bijak' AS ns1,
'http://schemas.datacontract.org/2004/07/Gbms.Dto' AS ns2,
'http://schemas.datacontract.org/2004/07/Gbms.Dto.VirginBijak' AS ns3)
INSERT INTO #TEMP_TABLE(ID, Date, Number)
SELECT
xc.value('(ns2:Id)[1]', 'int'),
xc.value('(ns3:Date)[1]', 'DateTime2'),
xc.value('(ns3:Number)[1]', 'int')
FROM
#XmlData.nodes('/ns1:ArrayOfEntityNested/ns1:EntityNested') AS xt(xc)
DECLARE #idoc int
DECLARE #doc varchar(1000)
SET #doc ='
<OutLookContact>
<Contact FirstName="Asif" LastName="Ghafoor" EmailAddress1="asifghafoor#my.web.pk" />
<Contact FirstName="Rameez" LastName="Ali" EmailAddress1="rameezali#my.web.pk" />
</OutLookContact>'
--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 #Temp TABLE(FirstName VARCHAR(250),LastName VARCHAR(250),Email1 VARCHAR(250))
INSERT INTO #Temp(FirstName,LastName,Email1)
SELECT *
FROM OPENXML (#idoc, '/OutLookContact/Contact',1)
WITH (FirstName varchar(50),LastName varchar(50),EmailAddress1 varchar(50))
select FirstName,LastName,Email1 from #Temp
it will be a lot easier if you try to use a tool called pentaho. http://en.wikipedia.org/wiki/Pentaho
it is an open source tool which is used for data integration.you can create a database connection from mysql or oracle to it and do the transformation.it is easy to use.
I have an XML file and I open that in SQL Server using OPENXML and then read the values in the XML file and insert them into the table. Assume that the XML structure is like this
<Student>
<name>XYZ</name>
<id>123</id>
<fathersname>XYS</fathersname>
<fathersid>3489</fathersid>
</Student>".
Now I need to add this as two different rows and the DB should look like this
Name ID XYZ 123XYS 3489 How can i read from thisXML and insert as two different rows using a single OPENXML statement?
CREATE TABLE dbo.Person(ID int, [Name] varchar(50))
DECLARE #docHandle int
DECLARE #xmlDocument XML
SET #xmlDocument = N'<ROOT>
<Student>
<name>XYZ</name>
<id>123</id>
<fathersname>XYS</fathersname>
<fathersid>3489</fathersid>
</Student>
<Student>
<name>ABC</name>
<id>456</id>
<fathersname>DEF</fathersname>
<fathersid>7859</fathersid>
</Student>
</ROOT>'
EXEC sp_xml_preparedocument #docHandle OUTPUT, #xmlDocument
-- student's data first
INSERT INTO dbo.Person
SELECT *
FROM OPENXML(#docHandle, N'/ROOT/Student',2)
WITH (id int, name varchar(50))
-- now insert father's data
INSERT INTO dbo.Person
SELECT *
FROM OPENXML(#docHandle, N'/ROOT/Student',2)
WITH (fathersid int, fathersname varchar(50))
SELECT * FROM dbo.Person
EXEC sp_xml_removedocument #docHandle
DROP TABLE dbo.Person
To open from a file:
declare #xmlDocument XML
SET #xmlDocument=(SELECT * FROM OPENROWSET(
BULK 'c:\Temp\Student.xml',
SINGLE_BLOB) AS x)
UPDATE:
Sorry, did not see that you are trying to split <father> into a different row, I have simply added one more INSERT for that. If you need more control over the loading process, you can always consider setting up an ETL job in SSIS.
UPDATE 2
Well here is a creative way with one insert only, but two selects -- not sure about the performance at all. Again, we are splitting one record into two rows.
INSERT INTO dbo.Person
SELECT
x.e.value('id[1]', 'int') AS "id"
,x.e.value('name[1]', 'varchar(10)') AS "Name"
FROM #xmlDocument.nodes('/ROOT/Student') AS x(e)
UNION
SELECT
x.e.value('fathersid[1]', 'int') AS "id"
,x.e.value('fathersname[1]', 'varchar(10)') AS "Name"
FROM #xmlDocument.nodes('/ROOT/Student') AS x(e);