Importing multiple xml files with T-SQL - sql

How can I insert multiple xml files into a SQL Server table?
I have managed to get only 1 named file with this script:
CREATE TABLE #ZSK70 (Name varchar(25) , Value varchar(30),);
INSERT INTO #ZSK70 (Name, Value)
SELECT X.variable.query('Name').value('.', 'varchar(25)'),
X.variable.query('Value').value('.', 'varchar(30)')
FROM (
SELECT CAST(x AS XML)
FROM OPENROWSET(
BULK 'path+filename.xml',
SINGLE_BLOB) AS T(x)
) AS T(x)
CROSS APPLY x.nodes('CollectedData/variable') AS X(variable);
Any help is kindly appreciated.

Related

Uniqueidentifier conversion failed when Importing XML file to SQL Server

I'm trying to import data from an XML file into a SQL Server table. However, I'm getting the error:
Conversion failed when converting from a character string to uniqueidentifier
It says it's in state 2 of Line 6 (Id3), but I assume the conversion is failing in other places.
XML:
<ImportExportObject>
<Objects>
<MyObject>
<Id>123e5c8c-a7fc-40da-440e-12348bc612e8</Id>
<Id2>123e5c8c-a7fc-40da-440e-12348bc612e8</Id2>
<Name>en</Name>
<Id3>123e5c8c-a7fc-40da-440e-12348bc612e8</Id3>
</MyObject>
</Objects>
</ImportExportObject>
SQL code:
INSERT INTO MyTable(ID, Id2, Name, Id3)
SELECT
MyXMLDocument.query('Id').value('.', 'uniqueidentifier'),
MyXMLDocument.query('Id2').value('.', 'uniqueidentifier'),
MyXMLDocument.query('Name').value('.', 'NVARCHAR(50)'),
MyXMLDocument.query('Id3').value('.', 'uniqueidentifier'),
FROM (SELECT CAST(MyXMLDocument AS xml)
FROM OPENROWSET(BULK 'C:\Users\myUser\Documents\MyXMLDocument.xml', SINGLE_BLOB) AS T(MyXMLDocument)) AS T(MyXMLDocument)
CROSS APPLY MyXMLDocument.nodes('ImportExportObject/Objects/MyObject') AS MyXMLDocument (MyObject);
How do I resolve this error?
I've been unable to get Select Cast and Convert to work - and .value() requires string literals so '#Id' doesn't seem to work.
Quite unsure here - any help is much appreciated!
How about having MyTable with an automatically imported id and not importing that? Would that work for what you want?
You can the code below to find which values cannot be converted to uniqueidentifier:
SELECT
MyXMLDocument.query('Id').value('.', 'NVARCHAR(50)'),
MyXMLDocument.query('Id2').value('.', 'NVARCHAR(50)'),
MyXMLDocument.query('Id3').value('.', 'NVARCHAR(50)')
FROM (SELECT CAST(MyXMLDocument AS xml)
FROM OPENROWSET(BULK 'C:\Users\myUser\Documents\MyXMLDocument.xml', SINGLE_BLOB) AS T(MyXMLDocument)) AS T(MyXMLDocument)
CROSS APPLY MyXMLDocument.nodes('ImportExportObject/Objects/MyObject') AS MyXMLDocument (MyObject)
WHERE TRY_CAST(MyXMLDocument.query('Id').value('.', 'NVARCHAR(50)') AS uniqueidentifier) IS NULL
OR TRY_CAST(MyXMLDocument.query('Id2').value('.', 'NVARCHAR(50)') AS uniqueidentifier) IS NULL
OR TRY_CAST(MyXMLDocument.query('Id3').value('.', 'NVARCHAR(50)') AS uniqueidentifier) IS NULL
The idea is to use TRY_CAST which will return NULL if the data cannot be converted.
declare #x xml = N'<ImportExportObject>
<Objects>
<MyObject>
<Id>123e5c8c-a7fc-40da-440e-12348bc612e8</Id>
<Id2>123e5c8c-a7fc-40da-440e-12348bc612e8</Id2>
<Name>en</Name>
<Id3>123e5c8c-a7fc-40da-440e-12348bc612e8</Id3>
</MyObject>
</Objects>
</ImportExportObject>';
SELECT
MyXML.MyObject.value('Id[1]', 'uniqueidentifier'),
MyXML.MyObject.value('Id2[1]', 'uniqueidentifier'),
MyXML.MyObject.value('Name[1]', 'NVARCHAR(50)'),
MyXML.MyObject.value('Id3[1]', 'uniqueidentifier')
FROM
(
SELECT #x
-- CAST(MyXMLDocument AS xml) FROM OPENROWSET(BULK 'C:\Users\myUser\Documents\MyXMLDocument.xml', SINGLE_BLOB)
) AS T(MyXMLDocument)
CROSS APPLY MyXMLDocument.nodes('./ImportExportObject/Objects/MyObject') AS MyXML(MyObject);

Update var binary to existing SQL columns (Add to existing image)?

I have a table City; my Pic column datatype is varbinary(max):
I update my pic column with this code and work (for 1 pic):
UPDATE City
SET pic = 0xwed323422222222....
WHERE id = 4
but how can I update 3 images or more in Pic column? (add to existing image)
It my means I stored in table where id = 4 just 1 image binary. How can I save more than 1 image in a single column?
You could store multiple images in a "semi-structured" way, within a single column by leveraging xml (and its structural integrity). You could change the datatype of the "pic" column to xml or keep it varbinary (some type casting is required for the latter).
The following example assumes varbinary storage for "the image" column and a "c:\testnew" folder (on the sql instance) which contains 3 images (image[1..3].png).
First, the two images are loaded for "the image" column of cityid=1 and later on the third image is appended to the binary data(first 2 pics) with update .write().
Removing images or inserting images in specific place within the blob could be achieved by utilizing the xml.modify() method.
All this, if you really need/have to store multiple images in a single row&column.
create table dbo.TestImages
(
id int identity(1,1) constraint pkidTestImages primary key clustered(id),
CityId int,
ImagesBlobXml varbinary(max) --or xml
)
go
--insert two images from folder c:\testnew
insert into dbo.TestImages
(
CityId, ImagesBlobXml
)
values (
1,
cast((
select TheImage
from
(
select *
from openrowset(bulk N'C:\testnew\image1.png', single_blob) as i(TheImage)
union all
select *
from openrowset(bulk N'C:\testnew\image2.png', single_blob) as i(TheImage)
--union all
--select *
--from openrowset(bulk N'C:\testnew\stackoverflow.png', single_blob) as i(TheImage)
) as images
for xml path(''), type
) as varbinary(max))
);
select 'table content', *
from dbo.TestImages;
--retrieve images (2)
select 'images in blob, initial insert', t.id, t.CityId, i.bin.value('.', 'varbinary(max)') as TheImage
from
(
select *, cast(ImagesBlobXml as xml) as ImagesBlobXmlXML
from dbo.TestImages
) as t
cross apply t.ImagesBlobXmlXML.nodes('TheImage') as i(bin);
--append new image
update t
set ImagesBlobXml .WRITE( --note:write cannot be used on NULL values
cast((
select TheImage
from
(
select *
from openrowset(bulk N'C:\testnew\image3.png', single_blob) as i(TheImage)
) as images
for xml path(''), type
) as varbinary(max)) ,
null, 0 --write() append
)
from dbo.TestImages as t
where CityId = 1;
--retrieve the images (3)
select 'images in blob, after update_append', t.id, t.CityId, i.bin.value('.', 'varbinary(max)') as TheImage
from
(
select *, cast(ImagesBlobXml as xml) as ImagesBlobXmlXML
from dbo.TestImages
) as t
cross apply t.ImagesBlobXmlXML.nodes('TheImage') as i(bin);
--check for any diff
select i.bin.value('.', 'varbinary(max)') as TheImage
from
(
select *, cast(ImagesBlobXml as xml) as ImagesBlobXmlXML
from dbo.TestImages
) as t
cross apply t.ImagesBlobXmlXML.nodes('TheImage') as i(bin)
except
select TheImage
from
(
select *
from openrowset(bulk N'C:\testnew\image1.png', single_blob) as i(TheImage)
union all
select *
from openrowset(bulk N'C:\testnew\image2.png', single_blob) as i(TheImage)
union all
select *
from openrowset(bulk N'C:\testnew\image3.png', single_blob) as i(TheImage)
) as images;
go
--cleanup
drop table dbo.TestImages;
go

Getting XML from two different files into a single SQL Table

I have the following query setup, that works with no problem:
WITH XmlFile (xmlData) AS
(
SELECT CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK 'D:\Timewise\results.xml', SINGLE_BLOB) AS x
)
INSERT INTO [dbo].[Timewise] ([Title], [IP])
SELECT c.value('(Title/text())[1]', 'VARCHAR(25)') AS [NameSite]
, 'video' as [JournalUserName]
, '' as [JournalPassword]
, c.value('(IP/text())[1]', 'VARCHAR(25)') AS [IPAddress]
, '4910' as [Port]
, 'video' as [VideoUserName]
, '' as [VideoPassword]
, c.value('(IP/text())[1]', 'VARCHAR(25)') AS [VideoIP]
, '4910' as [VideoPort]
, '1' as [TotalCams]
, '1' as [TotalVideoWindows]
, 'true' as [IsRemote]
, 'false' as [IsDefaultSite]
,'' as [hasTwoDifferentUsers]
, '' as [DVRType]
, 'false' as [IsRemoteLiveDataRunning]
FROM XmlFile CROSS APPLY xmlData.nodes('DocumentElement/Server_x0020_List') AS t(c);
The next issue is that some of these nodes contain data from another xml file, located at D:\Timewise\JournalBrowserSiteSettings.xml
I tried to do some research on these, to get an example, and while I have the WITH statement covered:
WITH XmlFile (xmlData) AS
(
SELECT CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK 'D:\Timewise\results.xml', SINGLE_BLOB) AS x
)
,
XmlFile2 (xmlData) AS
(
SELECT CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK 'D:\Timewise\JournalBrowserSiteSettings.xml', SINGLE_BLOB) AS y
)
I honestly have no idea how to pull this data (namely the TotalCams,TotalVideoWIndows,IsRemote, hasTwoDIfferentUsers, and DVRType) from the other file, and now almost 2 hours of searching has given me nothing to really go on.
It seems that you know how to get XML into SQL tables.
How about getting the XML files into two different tables and then joining the tables based on a common key, e.g. Title?
That will work. Won't it?

Is there a way to remove explicit attribute names in parsing XML data?

In my XML parsing query, I have:
SELECT Id, DeveloperId, PublisherId,
Data.value('(/Game/DeveloperName/text())[1]', 'nvarchar(50)') DeveloperName,
Data.value('(/Game/PublisherName/text())[1]', 'nvarchar(50)') PublisherName,
Data.value('(/Game/Genre/text())[1]', 'nvarchar(50)') Genre,
FROM GameDataTable;
I was wondering if it is possible to not explicitly write
'DeveloperName, Publisher, Genre'
to possibly make human error in typos less prevalent and reduce some space. I thought about creating a temporary table but is that not efficient?
If anyone had any tips, that'd be great.
One option is to normalize your data and then pivot (the pivot is optional)
Example
Declare #YourTable table (ID int,DeveloperID int,PublisherID int,Data xml)
Insert Into #YourTable values
(1,2365,10056,'<Game><DeveloperName>This is the Developer Name</DeveloperName><PublisherName>This is the Publisher Name</PublisherName><Genre>Drama</Genre></Game>')
Select *
From (
Select A.ID
,A.DeveloperID
,A.PublisherID
,B.*
From #YourTable A
Cross Apply (
Select NodeName = lvl2.n.value('local-name(.)', 'varchar(max)')
,NodeValue = lvl2.n.value('text()[1]', 'varchar(max)')
From Data.nodes('*') lvl1(n)
Cross Apply lvl1.n.nodes('*') lvl2(n)
) B
) src
Pivot (max(NodeValue) for NodeName in ([DeveloperName],[PublisherName],[Genre]) ) pvt
Returns
Without the Pivot

Splitting the data with comma separation in SQL Server

How to split the data in a column with comma separation?
I am attaching the images for my Input and my expecting output.
The following is the input:
enter link description here
The following is my expected output:
enter link description here
Please help me how I will get my required output with a SQL Server query
Thanks in advance,
Phani Kumar.
declare #t Table (ID INT,Groupname VARCHAR(10),Pid VARCHAR(20))
insert into #t (ID,Groupname,Pid)values (1,'xxxx','123,568,562,25')
insert into #t (ID,Groupname,Pid)values (2,'yyyy','2,356,321')
insert into #t (ID,Groupname,Pid)values (3,'zzzz','7,898,569')
insert into #t (ID,Groupname,Pid)values (4,'sss','12345')
SELECT ID,Groupname,
PARSENAME(REPLACE(Split.a.value('.', 'VARCHAR(100)'),'-','.'),1) 'Values'
FROM
(
SELECT ID,Groupname,
CAST ('<M>' + REPLACE([Pid], ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #t
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)