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?
Related
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);
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
I want to read xml data in the xml file.
I have a table column consist with the xml data.
if i click on the xml file it will open in the Sql server Management studio.
xml file format shown below.
I want to read only NTDomainName, DatabaseName and ServerName and write that data in the another Table. Table format shown below
NTDomainName | DatabaseName | ServerName
----------
ABC | TestCube1 | SERXYZ
Try this:
declare #xml xml
set #xml = '<event><data name="NTUserName"><value>MyName</value></data><data name="NTDomainName"><value>DomainName</value></data><data name="ServerName"><value>ServerName</value></data></event>'
select [NTDomainName], [DatabaseName], [ServerName] from
(
select [name],[value] from (
select c.value('./#name', 'varchar(100)') [name], c.value('(./value)[1]', 'varchar(100)') [value]
from #xml.nodes('/event/data') as t(c)
) a where [name] in ('NTDomainName', 'DatabaseName', 'ServerName')
) x
pivot (
max(value) for [name] in ([NTDomainName], [DatabaseName], [ServerName])
) as [pivot_Name]
The most inner query will retrieve information from XML, one row for every name attribute value, that you want to retrieve. So, output of this query needs to be pivoted.
i think you look for this:
SELECT * FROM (
SELECT
CAST(f.x.query('data(#name)') as varchar(150)) as data_name,
CAST(f.x.query('data(value)') as varchar(150)) as data_value
FROM #xml.nodes('/event') as t(n)
CROSS APPLY t.n.nodes('data') as f(x)) X
PIVOT (MAX(data_value) FOR data_name IN (NTDomainName, DatabaseName, ServerName)) as pvt
If you do not want to use PIVOT:
DECLARE #DataSource TABLE
(
[ID] TINYINT IDENTITY(1,1)
,[XML] XML
);
INSERT INTO #DataSource ([XML])
VALUES ('<event><data name="SessionID">S1</data><data name="NTUserName">User1</data><data name="DatabaseName">DB1</data><data name="ServerName">SN1</data></event>')
,('<event><data name="SessionID">S1</data><data name="NTUserName">User2</data><data name="DatabaseName">DB2</data><data name="ServerName">SN2</data></event>');
SELECT [ID]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'NTUserName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [NTUserName]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'DatabaseName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [DatabaseName]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'ServerName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [ServerName]
FROM #DataSource
CROSS APPLY [XML].nodes('event/data[#name = "NTUserName" or #name = "DatabaseName" or #name = "ServerName"]') T(c)
GROUP BY [ID];
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.
Here's a link to my previous question on this same block of code with a working shred example
Ok, I'm a C# ASP.NET dev following orders: The orders are to take a given dataset, shred the XML and return columns. I've argued that it's easier to do the shredding on the ASP.NET side where we already have access to things like deserializers, etc, and the entire complex of known types, but no, the boss says "shred it on the server, return a dataset, bind the dataset to the columns of the gridview" so for now, I'm doing what I was told. This is all to head off the folks who will come along and say "bad requirements".
Task at hand:
Current code that doesn't work:
And if we modify the previous post to include namespaces on the XML elements, we lose the functionality that the previous post has...
DECLARE #table1 AS TABLE (
ProductID VARCHAR(10)
, Name VARCHAR(20)
, Color VARCHAR(20)
, UserEntered VARCHAR(20)
, XmlField XML
)
INSERT INTO #table1 SELECT '12345','ball','red','john','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>10</price></size><size xmlns="http://example.com/ns" name="large"><price>20</price></size></sizes>'
INSERT INTO #table1 SELECT '12346','ball','blue','adam','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>12</price></size><size xmlns="http://example.com/ns" name="large"><price>25</price></size></sizes>'
INSERT INTO #table1 SELECT '12347','ring','red','john','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>5</price></size><size xmlns="http://example.com/ns" name="large"><price>8</price></size></sizes>'
INSERT INTO #table1 SELECT '12348','ring','blue','adam','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>8</price></size><size xmlns="http://example.com/ns" name="large"><price>10</price></size></sizes>'
INSERT INTO #table1 SELECT '23456','auto','black','ann','<auto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><type xmlns="http://example.com/ns">car</type><wheels xmlns="http://example.com/ns">4</wheels><doors xmlns="http://example.com/ns">4</doors><cylinders xmlns="http://example.com/ns">3</cylinders></auto>'
INSERT INTO #table1 SELECT '23457','auto','black','ann','<auto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><type xmlns="http://example.com/ns">truck</type><wheels xmlns="http://example.com/ns">4</wheels><doors xmlns="http://example.com/ns">2</doors><cylinders xmlns="http://example.com/ns">8</cylinders></auto><auto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><type xmlns="http://example.com/ns">car</type><wheels xmlns="http://example.com/ns">4</wheels><doors xmlns="http://example.com/ns">4</doors><cylinders xmlns="http://example.com/ns">6</cylinders></auto>'
DECLARE #x XML
-- I think I'm supposed to use WITH XMLNAMESPACES(...) here but I don't know how
SELECT #x = (
SELECT
ProductID
, Name
, Color
, UserEntered
, XmlField.query('
for $vehicle in //auto
return <auto
type = "{$vehicle/type}"
wheels = "{$vehicle/wheels}"
doors = "{$vehicle/doors}"
cylinders = "{$vehicle/cylinders}"
/>')
FROM #table1 table1
WHERE Name = 'auto'
FOR XML AUTO
)
SELECT #x
SELECT
ProductID = T.Item.value('../#ProductID', 'varchar(10)')
, Name = T.Item.value('../#Name', 'varchar(20)')
, Color = T.Item.value('../#Color', 'varchar(20)')
, UserEntered = T.Item.value('../#UserEntered', 'varchar(20)')
, VType = T.Item.value('#type' , 'varchar(10)')
, Wheels = T.Item.value('#wheels', 'varchar(2)')
, Doors = T.Item.value('#doors', 'varchar(2)')
, Cylinders = T.Item.value('#cylinders', 'varchar(2)')
FROM #x.nodes('//table1/auto') AS T(Item)
If my previous post shows there's a much better way to do this, then I really need to revise this question as well, but on the off chance this coding-style is good, I can probably go ahead with this as-is.
DECLARE #x XML;
with xmlnamespaces ('http://www.w3.org/2001/XMLSchema-instance' as xsi
, 'http://www.w3.org/2001/XMLSchema' as xsd
, 'http://example.com/ns' as ns)
SELECT #x = (
SELECT
ProductID
, Name
, Color
, UserEntered
, XmlField.query('
for $vehicle in //auto
return <auto
type = "{$vehicle/ns:type}"
wheels = "{$vehicle/ns:wheels}"
doors = "{$vehicle/ns:doors}"
cylinders = "{$vehicle/ns:cylinders}"
/>')
FROM #table1 table1
WHERE Name = 'auto'
FOR XML AUTO
)