Uniqueidentifier conversion failed when Importing XML file to SQL Server - sql

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);

Related

Import xml data in SQL Server 2017

I have XML data like this:
<?xml version="1.0" ?>
<SettlementFile>
<Transaction>
<Identifier>
<StationID>049215901 </StationID>
<TransactionTimestamp>2021-04-01T10:39:32</TransactionTimestamp>
</Identifier>
<TerminalInfo>
<TerminalID>21590151</TerminalID>
<TerminalType>2</TerminalType>
</TerminalInfo>
<TransactionInfo>
<TransactionType>0</TransactionType>
<TransactionAmount>3.74</TransactionAmount>
<CurrencyCode>978</CurrencyCode>
<CustomerInput>
<Mileage>0</Mileage>
</CustomerInput>
<TicketNumber>213510037</TicketNumber>
<AuthorisationType>1</AuthorisationType>
</TransactionInfo>
</Transaction>
</SettlementFile>
My SQL Server table structure:
CREATE TABLE dbo.Import_Oase
(
StationID varchar(50) NULL,
TransactionTimestamp datetime NULL,
TicketNumber int NULL,
Mileage varchar(50) NULL
) ON PRIMARY
I'm trying to use this SELECT query:
SELECT
MY_XML.Details.query('StationID') .value('.', 'VARCHAR(50)'),
MY_XML.Details.query('TransactionTimestamp').value('.', 'Datetime'),
MY_XML.Details.query('TicketNumber') .value('.', 'Integer'),
MY_XML.Details.query('Mileage') .value('.', 'VARCHAR(50)')
FROM
(SELECT
CAST(MY_XML AS XML)
FROM
OPENROWSET(BULK '\\EO-TEST\SQL-Daten\Temp\MY_XML.xml', SINGLE_BLOB) AS T(MY_XML)
) AS T(MY_XML)
CROSS APPLY
MY_XML.nodes('SettlementFile/Transaction/Identifier, SettlementFile/Transaction/TransactionInfo, SettlementFile/Transaction/TransactionInfo/CustomerInput') AS MY_XML (Details);
I need to get the result in one line because it is all for 1 transactions. But it is in three different line in SQL.
Please try the following solution.
When you are satisfied with the outcome, just uncomment the INSERT INTO line.
SQL
WITH rs (xmlData) AS
(
SELECT TRY_CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK N'e:\Temp\ daryosmitan.xml', SINGLE_BLOB) AS x
)
-- INSERT INTO dbo.Import_Oase (StationID, TransactionTimestamp, TicketNumber, Mileage)
SELECT c.value('(Identifier/StationID/text())[1]', 'VARCHAR(50)') AS StationID
, c.value('(Identifier/TransactionTimestamp/text())[1]', 'DATETIME') AS TransactionTimestamp
, c.value('(TransactionInfo/TicketNumber/text())[1]', 'VARCHAR(50)') AS TicketNumber
, c.value('(TransactionInfo/CustomerInput/Mileage/text())[1]', 'INT') AS Mileage
FROM rs
CROSS APPLY xmlData.nodes('/SettlementFile/Transaction') AS t(c);

how to execute subquery without declaring XML?

why this query is not executing ??
SELECT [Value] = T.c.value('.','varchar(30)') FROM (SELECT '<s>'+ REPLACE ((select tag_id+',' from tbl_container_track for xml path('')),',','</s> <s>')+ '</s>').nodes('/s') T(c)
But this one is working ?
declare #X xml
SELECT #X = (SELECT '<s>'+ REPLACE ((select tag_id+',' from tbl_container_track for xml path('')),',','</s> <s>')+ '</s>')
SELECT [Value] = T.c.value('.','varchar(30)') FROM #X.nodes('/s') T(c)
Can some one help me to simplify without declaring #X ?
Try this: CAST TO XML Datatype you missed
SELECT [Value] = T.c.value('.', 'varchar(30)')
FROM (SELECT Cast(( '<s>' + Replace ((SELECT tag_id+',' FROM tbl_container_track FOR xml path('')), ',', '</s> <s>')
+ '</s>' ) AS XML)) AS Data
CROSS APPLY Data.nodes('/s') T(c)

Selecting XML Data from SQL query - No values returned

Xml Column returns no rows.
Below created a table type and xml value inserted into that table. After executing the below mentioned two queries no value is returned.
Xml data is a valid data.
DECLARE #Test TABLE (Id INT IDENTITY (1,1), XMLDATA XML)
INSERT INTO #test
SELECT '
<TXLife xmlns="http://ACORD.org/Standards/Life/2" xmlns:tx="http://ACORD.org/Standards/Life/2" Version="2.20.00">
<TXLifeRequest PrimaryObjectID="Holding_1">
<CorrelationGUID>4b30545a-158b-441a-a37a-0b259f757059</CorrelationGUID>
</TXLifeRequest>
</TXLife>'
SELECT
Id
, XMLDATA.query('//CorrelationGUID') AS 'TransType'
, XMLDATA
FROM #test
SELECT C.value('./CorrelationGUID[1]', 'varchar(50)') AS 'TransType'
FROM #test
CROSS APPLY XMLDATA.nodes('/TXLife/TXLifeRequest') n (C)
Well, if I test your code with CREATE TABLE, here and here, the unfiltered select works just fine. However, the second filtered select returns no results.
If I alter the query to to specify the right namespace, like in #Devart's answer,
WITH XMLNAMESPACES (DEFAULT 'http://ACORD.org/Standards/Life/2')
SELECT
C.value('./CorrelationGUID[1]', 'varchar(50)') AS 'TransType'
FROM
Test
CROSS APPLY
XMLDATA.nodes('/TXLife/TXLifeRequest') n (C)
You can see, it works as expected.
Try this one -
DECLARE #XML XML
SELECT #XML = '
<TXLife xmlns="http://ACORD.org/Standards/Life/2" xmlns:tx="http://ACORD.org/Standards/Life/2" Version="2.20.00">
<TXLifeRequest PrimaryObjectID="Holding_1">
<CorrelationGUID>4b30545a-158b-441a-a37a-0b259f757059</CorrelationGUID>
</TXLifeRequest>
</TXLife>'
;WITH XMLNAMESPACES (DEFAULT 'http://ACORD.org/Standards/Life/2')
SELECT t.c.value('CorrelationGUID[1]', 'UNIQUEIDENTIFIER')
FROM #XML.nodes('//TXLifeRequest') t(c)
Output -
------------------------------------
4B30545A-158B-441A-A37A-0B259F757059
You need to declare the namespace. Try this:
SELECT
XMLDATA.value('declare namespace L="http://ACORD.org/Standards/Life/2";(//L:CorrelationGUID)[1]',
'UNIQUEIDENTIFIER') AS 'TransType'
FROM #test
UNION ALL
SELECT
C.value('declare namespace L="http://ACORD.org/Standards/Life/2";(./L:CorrelationGUID)[1]',
'UNIQUEIDENTIFIER') AS 'TransType'
FROM #test
CROSS APPLY
XMLDATA.nodes('declare namespace L="http://ACORD.org/Standards/Life/2";/L:TXLife/L:TXLifeRequest') N(C)
See it working here.

Importing multiple xml files with T-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.

SQL: How can I get the value of an attribute in XML datatype?

I have the following xml in my database:
<email>
<account language="en" ... />
</email>
I am using something like this now: but still have to find the attribute value.
SELECT convert(xml,m.Body).query('/Email/Account')
FROM Mail
How can I get the value of the language attribute in my select statement with SQL?
Use XQuery:
declare #xml xml =
'<email>
<account language="en" />
</email>'
select #xml.value('(/email/account/#language)[1]', 'nvarchar(max)')
declare #t table (m xml)
insert #t values
('<email><account language="en" /></email>'),
('<email><account language="fr" /></email>')
select m.value('(/email/account/#language)[1]', 'nvarchar(max)')
from #t
Output:
en
fr
This should work:
DECLARE #xml XML
SET #xml = N'<email><account language="en" /></email>'
SELECT T.C.value('#language', 'nvarchar(100)')
FROM #xml.nodes('email/account') T(C)
It depends a lot on how you're querying the document. You can do this, though:
CREATE TABLE #example (
document NText
);
INSERT INTO #example (document)
SELECT N'<email><account language="en" /></email>';
WITH XmlExample AS (
SELECT CONVERT(XML, document) doc
FROM #example
)
SELECT
C.value('#language', 'VarChar(2)') lang
FROM XmlExample CROSS APPLY
XmlExample.doc.nodes('//account') X(C);
DROP TABLE #example;
EDIT after changes to your question.
if the xml data is stored in sql server as a string column then use cast
select cast(your_field as XML)
.value('(/email/account/#language)[1]', 'varchar(20)')
from your_table