Open XML select values with XML name space - sql-server

I am trying to select some values using open xml in sql server 2012. This works when I don't have any xml name space. But whenever the below prefix get added with root element, I am not able to select values. Any suggestion how I can select values with xmlns:
xmlns="somenamspace/2006-10-31" order-no="00000001"
USE grails
GO
DECLARE #XML AS XML, #hDoc AS INT, #SQL NVARCHAR (MAX), #rootxmlns varchar(100)
SELECT #XML = N'<order xmlns="somenamspace/2006-10-31" order-no="00000001">
<order-date>2017-07-24T20:48:57.000Z</order-date>
<original-order-no>00000001</original-order-no>
<customer>
<customer-name>abcd abcd</customer-name>
<customer-email>jjj#gmail.com</customer-email>
</customer>
<current-order-no>00000001</current-order-no>
<payments>
<payment>
<credit-card>
<card-type>VISA</card-type>
<card-number>XXXX-XXXX-XXXX-1111</card-number>
<card-holder>abcd</card-holder>
<expiration-month>1</expiration-month>
<expiration-year>2021</expiration-year>
</credit-card>
<amount>325.48</amount>
</payment>
</payments>
</order>';
SET #rootxmlns = '<root xmlns:ns1="somenamspace/2006-10-31"/>'
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML, #rootxmlns
SELECT orderNo
FROM OPENXML(#hDoc, 'ns1:order',2)
WITH
(
orderNo [varchar](50) 'original-order-no'
)
SELECT *
FROM OPENXML(#hDoc, 'ns1:order/customer',2)
WITH
(
customerName [varchar](50) 'customer-name',
customerEmail [varchar](100) 'customer-email'
)
SELECT cardType, cardNumber, cardHolder
FROM OPENXML(#hDoc, '/order/payments/payment/credit-card',2)
WITH
(
cardType [varchar](50) 'card-type',
cardNumber [varchar](100) 'card-number',
cardHolder [varchar](100) 'card-holder'
)
EXEC sp_xml_removedocument #hDoc
GO

Great, that you've found an answer yourself, but this can be solved better.
FROM OPENXML with the corresponding SPs to open and to remove a document is outdated and should not be used any more. Rather use the methods, the native XML type provides:
The following will give you at least some templates how to access the values within your XML:
DECLARE #XML AS XML=
N'<order xmlns="somenamspace/2006-10-31" order-no="00000001">
<order-date>2017-07-24T20:48:57.000Z</order-date>
<original-order-no>00000001</original-order-no>
<customer>
<customer-name>abcd abcd</customer-name>
<customer-email>jjj#gmail.com</customer-email>
</customer>
<current-order-no>00000001</current-order-no>
<payments>
<payment>
<credit-card>
<card-type>VISA</card-type>
<card-number>XXXX-XXXX-XXXX-1111</card-number>
<card-holder>abcd</card-holder>
<expiration-month>1</expiration-month>
<expiration-year>2021</expiration-year>
</credit-card>
<amount>325.48</amount>
</payment>
</payments>
</order>';
--The query
WITH XMLNAMESPACES(DEFAULT N'somenamspace/2006-10-31')
SELECT #xml.value(N'(/order/#order-no)[1]',N'int') AS OrderNumber
,#xml.value(N'(/order/order-date/text())[1]',N'datetime') AS OrderDate
,#xml.value(N'(/order/customer/customer-name/text())[1]',N'nvarchar(max)') AS CustomerName
,p.value(N'local-name(.)',N'nvarchar(max)') AS PaymentType
,p.value(N'(card-type/text())[1]','nvarchar(max)') AS CardType
,p.value(N'(../amount/text())[1]','decimal(10,4)') AS Amount
FROM #xml.nodes(N'/order/payments/payment/*[local-name()!="amount"]') AS A(p)
The result
Nr OrderDate CustomerName PaymentType CardType Amount
1 2017-07-24 20:48:57.000 abcd abcd credit-card VISA 325.4800
Explanation
Some data is taken directly via XPath out of #xml. The statement FROM #xml.nodes() will create a derived table of <payments><payment> nodes (as the wording suggests a 1:n relationship. The <amount> node is handled explicitly, the other node within <payment> is taken as payment details.

Got it,need to add name space in property level as well:
SET #rootxmlns = '<root xmlns:ns1="http://www.demandware.com/xml/impex/order/2006-10-31"/>'
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML, #rootxmlns
SELECT orderNo
FROM OPENXML(#hDoc, 'ns1:order',2)
WITH
(
orderNo [varchar](50) 'ns1:original-order-no'
)
SELECT *
FROM OPENXML(#hDoc, 'ns1:order/ns1:customer',2)
WITH
(
customerName [varchar](50) 'ns1:customer-name',
customerEmail [varchar](100) 'ns1:customer-email'
)
SELECT cardType, cardNumber, cardHolder
FROM OPENXML(#hDoc, 'ns1:order/ns1:payments/ns1:payment/ns1:credit-card',2)
WITH
(
cardType [varchar](50) 'ns1:card-type',
cardNumber [varchar](100) 'ns1:card-number',
cardHolder [varchar](100) 'ns1:card-holder'
)
EXEC sp_xml_removedocument #hDoc
GO

Related

Insert XML data into multiple tables in SQL Server

I have a XML like below :
<Employees>
<Employee>
<AccountInfo>
<AccountNumber>1234567</AccountNumber>
<AccountType>Test</AccountType>
</AccountInfo>
<DocumentType>Test Doc</DocumentType>
<Date>12/01/2020</Date>
<Description>Test Description</Description>
<ImageFileType>pdf</ImageFileType>
<ImageFileName>321.PDF</ImageFileName>
<AdditionalInfo>
<FieldName>docDescription</FieldName>
<FieldValue>ABC XYZ</FieldValue>
</AdditionalInfo>
<AdditionalInfo>
<FieldName>Creation Date</FieldName>
<FieldValue>12/01/2020</FieldValue>
</AdditionalInfo>
<AdditionalInfo>
<FieldName>Department Code</FieldName>
<FieldValue>63</FieldValue>
</AdditionalInfo>
<AdditionalInfo>
<FieldName>ID No</FieldName>
<FieldValue>3214567</FieldValue>
</AdditionalInfo>
</Employee>
</Employees>
I want to insert this XML data into 3 tables EmployeeInfo, AccountInfo and AdditionalInfo with schema like this:
EmployeeInfo
(
EmployeeNumber Int Identity(1,1) NOT NULL,
DocumentType varchar(500) NULL,
[Description] varchar(500) NULL,
ImageFileName varchar(500) NULL,
ImageFileType varchar(500) NULL,
[Date] varchar(500) NULL
);
AccountInfo
(
EmployeeNumber int NOT NULL,
AccountNumber varchar(500) NULL,
AccountType varchar(500) NULL
);
AdditionalInfo
(
EmployeeNumber int NOT NULL,
FieldName varchar(500) NULL,
FieldValue varchar(500) NULL
);
EmployeeNumber column is used for linking AccountInfo and AdditionalInfo table with EmployeeInfo.
AccountInfo table will get below node:
<AccountInfo>
<AccountNumber>1234567</AccountNumber>
<AccountType>Test</AccountType>
</AccountInfo>
The AdditionalInfo table will get these XML nodes:
<AdditionalInfo>
<FieldName>docDescription</FieldName>
<FieldValue>ABC XYZ</FieldValue>
</AdditionalInfo>
<AdditionalInfo>
<FieldName>Creation Date</FieldName>
<FieldValue>12/01/2020</FieldValue>
</AdditionalInfo>
<AdditionalInfo>
<FieldName>Department Code</FieldName>
<FieldValue>63</FieldValue>
</AdditionalInfo>
<AdditionalInfo>
<FieldName>ID No</FieldName>
<FieldValue>3214567</FieldValue>
</AdditionalInfo>
Rest xml node are inserted into EmployeeInfo.
I tried with the query shown here. I'm able to get xml data and insert it into main table EmployeeInfo, but not able to link AdditionalInfo and AccountInfo with identity generated in EmployeeInfo table.
Note: I have multiple employee nodes in the xml.
DECLARE #EmpNumber int
DECLARE #x xml
SELECT #x = X FROM OPENROWSET (BULK 'C:\Test\Sample.xml', SINGLE_BLOB) AS EmpInfo(X)
DECLARE #hdoc int
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x
INSERT INTO EmployeeInfo (DocumentType, [Description], ImageFileName, ImageFileType, [Date])
SELECT * FROM OPENXML (#hdoc, '/Employees/Employee', 2)
WITH ( DocumentType varchar(500), [Description] varchar(500), ImageFileName varchar(500), ImageFileType varchar(500), [Date] varchar(500))
SELECT #EmpNumber=SCOPE_IDENTITY()
INSERT INTO AccountInfo ([EmployeeNumber],[AccountNumber], [AccountType])
SELECT #EmpNumber, *
FROM OPENXML (#hdoc, '/Employees/Employee/AccountInfo', 2)
WITH (AccountNumber varchar(500), AccountType varchar(500))
INSERT INTO AdditionalInfo ([EmployeeNumber],[FieldName], [FieldValue])
SELECT #EmpNumber, *
FROM OPENXML (#hdoc, '/Employees/Employee/AdditionalInfo', 2)
WITH (
FieldName varchar(5000), FieldValue varchar(5000)
)
EXEC sp_xml_removedocument #hdoc
Can someone help me out in this. Thanks in Advance.
Here is a conceptual example how to do it.
Two tables, state as a parent, and city as a child, with one-to-many relationship. Primary keys are IDENTITY based.
INSERT into a parent table generates new IDENTITY values that are captured and stored in a table variable, and later used to INSERT into a child table to preserve foreign key constraint.
SQL
-- DDL and sample data population, start
USE tempdb;
GO
DROP TABLE IF EXISTS #city;
DROP TABLE IF EXISTS #state;
-- parent table
CREATE TABLE #state (
stateID INT IDENTITY PRIMARY KEY,
stateName VARCHAR(30),
abbr CHAR(2),
capital VARCHAR(30)
);
-- child table (1-to-many)
CREATE TABLE #city (
cityID INT IDENTITY,
stateID INT NOT NULL FOREIGN KEY REFERENCES #state(stateID),
city VARCHAR(30),
[population] INT,
PRIMARY KEY (cityID, stateID, city)
);
-- mapping table to preserve IDENTITY ids
DECLARE #idmapping TABLE (GeneratedID INT PRIMARY KEY,
NaturalID VARCHAR(20) NOT NULL UNIQUE);
DECLARE #xml XML =
N'<root>
<state>
<StateName>Florida</StateName>
<Abbr>FL</Abbr>
<Capital>Tallahassee</Capital>
<cities>
<city>
<city>Miami</city>
<population>470194</population>
</city>
<city>
<city>Orlando</city>
<population>285713</population>
</city>
</cities>
</state>
<state>
<StateName>Texas</StateName>
<Abbr>TX</Abbr>
<Capital>Austin</Capital>
<cities>
<city>
<city>Houston</city>
<population>2100263</population>
</city>
<city>
<city>Dallas</city>
<population>5560892</population>
</city>
</cities>
</state>
</root>';
-- DDL and sample data population, end
;WITH rs AS
(
SELECT stateName = p.value('(StateName/text())[1]', 'VARCHAR(30)'),
abbr = p.value('(Abbr/text())[1]', 'CHAR(2)'),
capital = p.value('(Capital/text())[1]', 'VARCHAR(30)')
FROM #xml.nodes('/root/state') AS t(p)
)
MERGE #state AS o
USING rs ON 1 = 0
WHEN NOT MATCHED THEN
INSERT(stateName, abbr, capital)
VALUES(rs.stateName, rs.Abbr, rs.Capital)
OUTPUT inserted.stateID, rs.stateName
INTO #idmapping (GeneratedID, NaturalID);
;WITH Details AS
(
SELECT NaturalID = p.value('(StateName/text())[1]', 'VARCHAR(30)'),
city = c.value('(city/text())[1]', 'VARCHAR(30)'),
[population] = c.value('(population/text())[1]', 'INT')
FROM #xml.nodes('/root/state') AS A(p) -- parent
CROSS APPLY A.p.nodes('cities/city') AS B(c) -- child
)
INSERT #city (stateID, city, [Population])
SELECT m.GeneratedID, d.city, d.[Population]
FROM Details AS d
INNER JOIN #idmapping AS m ON d.NaturalID = m.NaturalID;
-- test
SELECT * FROM #state;
SELECT * FROM #idmapping;
SELECT * FROM #city;
Avoid using sp_xml_preparedocument, OPENXML and sp_xml_removedocument because they are inefficient, often cause resource leakage when sp_xml_removedocument is forgotten, and encourage RBAR-like constructs in what's supposed to be a set-based RDBMS.
Prefer to use nodes() and value() where possible, such as with the following...
insert dbo.EmployeeInfo (DocumentType, [Description], ImageFileName, ImageFileType, [Date])
select
Employee.value('(DocumentType/text())[1]', 'varchar(500)'),
Employee.value('(Description/text())[1]', 'varchar(500)'),
Employee.value('(ImageFileName/text())[1]', 'varchar(500)'),
Employee.value('(ImageFileType/text())[1]', 'varchar(500)'),
Employee.value('(Date/text())[1]', 'varchar(500)')
from #xml.nodes('/Employees/Employee') root(Employee);
declare #EmpNumber int = SCOPE_IDENTITY();
insert dbo.AccountInfo ([EmployeeNumber], [AccountNumber], [AccountType])
select
#EmpNumber,
AccountInfo.value('(AccountNumber/text())[1]', 'varchar(500)'),
AccountInfo.value('(AccountType/text())[1]', 'varchar(500)')
from #xml.nodes('/Employees/Employee/AccountInfo') root(AccountInfo);
insert dbo.AdditionalInfo ([EmployeeNumber], [FieldName], [FieldValue])
select
#EmpNumber,
AdditionalInfo.value('(FieldName/text())[1]', 'varchar(500)'),
AdditionalInfo.value('(FieldValue/text())[1]', 'varchar(500)')
from #xml.nodes('/Employees/Employee/AdditionalInfo') root(AdditionalInfo);

Issue inserting into a temp table in SQL Server 2012

I'm trying to insert some XML data from a XML column into a temp table in SQL Server 2012.
This is my current query
DECLARE #XML AS XML, #hDoc AS INT, #SQL NVARCHAR (MAX)
IF OBJECT_ID('tempdb..dbo.#txn','u') IS NOT NULL
BEGIN
PRINT '#temp exists! drop table'
DROP TABLE tempdb.dbo.#txn;
END
ELSE
BEGIN
PRINT '#temp does not exist! create table'
CREATE TABLE #txn
(
accountcode varchar(100),
tienda varchar(100),
caja varchar(100),
cajero varchar(100),
fecha varchar(100),
transaccion varchar(100),
itemcode varchar(100),
description varchar(100),
quantity numeric(10,3),
weight numeric(10,3),
qty_weight numeric(10,3),
unitprice numeric(15,3),
totalprice numeric(15,3),
vatcode varchar(100),
hashcode varchar(100),
anulado varchar(100)
)
END
SELECT #XML = [LoadedXML] FROM [dbo].[XmlImport]
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML
INSERT INTO #txn (accountcode, tienda, caja, cajero, fecha, transaccion, itemcode, description, quantity, weight, qty_weight, unitprice, totalprice, vatcode, hashcode, anulado)
SELECT
CASE
WHEN codigotienda = 1 THEN '01'
END as accountcode,
tienda,
caja,
cajero,
fecha,
transaccion,
itemcode,
description,
quantity,
weight,
CASE
WHEN quantity IS NULL THEN weight
WHEN weight IS NULL THEN quantity
END as qty_weight,
unitprice,
totalprice,
CASE
WHEN vatcode = 4 THEN 'V0'
WHEN vatcode = 1 THEN 'V1'
WHEN vatcode = 2 THEN 'V2'
WHEN vatcode = 3 THEN 'V3'
WHEN vatcode is NULL THEN 'V0'
END AS vatcode,
hashcode,
anulado
FROM
OPENXML(#hDoc, 'tcpos-export/transactions/transaction/trans-item')
WITH
(
codigotienda [varchar](100) '../shop/code',
tienda [varchar](100) '../shop/description',
caja [varchar](100) '../till/code',
cajero [varchar](100) '../cashier/code',
fecha [varchar](100) '../beginning-timestamp',
transaccion [varchar](100) '../trans-num',
itemcode [varchar](100) 'code',
description [varchar](100) 'description',
quantity numeric(10,3) 'quantity',
weight numeric(10,3) 'weight',
unitprice numeric(15,3) 'unit-price',
totalprice numeric(15,3) 'taxable-amount',
vatcode [varchar](100) 'vat-code',
hashcode [varchar](100) 'hash-code',
anulado [varchar](100) 'delete-operator-id'
)
SELECT *
FROM #txn
WHERE hashcode IS NOT NULL
AND totalprice NOT LIKE '%-%'
AND unitprice NOT LIKE '%-%'
AND anulado IS NULL
ORDER BY
CAST(hashcode AS int)
--LEFT JOIN [MAXIMERCADODEMO].[dbo].OITM sap
--ON #txn.itemcode = sap.itemcode COLLATE SQL_Latin1_General_CP1_CI_AS
--where #txn.itemcode is null
--SELECT #txn.itemcode FROM #txn
--LEFT JOIN [MAXIMERCADODEMO].[dbo].OITM sap
--ON #txn.itemcode = sap.itemcode COLLATE SQL_Latin1_General_CP1_CI_AS
--where #txn.itemcode is null
EXEC sp_xml_removedocument #hDoc
This works the first time. When I run it a second time, it should drop the temp table, but I get this error instead:
#temp does not exist! create table
Msg 2714, Level 16, State 6, Line 11
There is already an object named '#txn' in the database.
I don't know if you guys recommend me using a temp table or create a real table in my database to manage this situation?
This
IF OBJECT_ID('tempdb..#txn','u') IS NOT NULL
Should be
IF OBJECT_ID('tempdb..#txn', 'u') IS NOT NULL DROP TABLE #txn;
You could even get away with just:
IF OBJECT_ID('tempdb..#txn') IS NOT NULL
Once you make this change you no longer need the big IF statement checking for this.
Do yourself a favour and don't use that ancient XML procedure OPENXML. Instead use .nodes and .value
You can even use XQuery predicates instead of the WHERE clause
SELECT CASE
WHEN trans.value('(shop/code/text())[1]','varchar(100)') = '1' THEN '01'
END as accountcode,
trans.value('(shop/description/text())[1]','varchar(100)') tienda,
trans.value('(till/code/text())[1]','varchar(100)') caja,
trans.value('(cashier/code/text())[1]','varchar(100)') cajero,
trans.value('(beginning-timestamp/text())[1]','varchar(100)') fecha,
trans.value('(trans-num/text())[1]','varchar(100)') transaccion,
item.value('(code/text())[1]','varchar(100)') itemcode,
item.value('(description/text())[1]','varchar(100)') description,
v.quantity,
v.weight,
CASE
WHEN v.quantity is null THEN v.weight
WHEN v.weight is null THEN v.quantity
END as qty_weight,
item.value('(unit-price/text())[1]','numeric(15,3)') unitprice,
item.value('(taxable-amount/text())[1]','numeric(15,3)') totalprice,
CASE
WHEN vatcode = '4' THEN 'V0'
WHEN vatcode = '1' THEN 'V1'
WHEN vatcode = '2' THEN 'V2'
WHEN vatcode = '3' THEN 'V3'
WHEN vatcode is NULL THEN 'V0'
END AS vatcode,
item.value('(hash-code/text())[1]','int') hashcode,
item.value('(delete-operator-id/text())[1]','varchar(100)') anulado
FROM [dbo].[XmlImport] xi
CROSS APPLY xi.[LoadedXML].nodes('tcpos-export/transactions/transaction') x1(trans)
CROSS APPLY x1.trans.nodes('trans-item[
hash-code/text() and
not( unit-price[contains(text()[1], "-")] ) and
not( taxable-amount[contains(text()[1], "-")] ) and
not( delete-operator-id/text() )
]') x2(item)
CROSS APPLY (VALUES (
item.value('(quantity/text())[1]','numeric(10,3)'),
item.value('(weight/text())[1]','numeric(10,3)'),
item.value('(vat-code/text())[1]','varchar(100)')
) ) v(quantity, weight, vatcode)
ORDER BY hashcode;

Reading XML attribute values using OPENXML

For the following .nodes() approach, I need an equivalent OPENXML approach. The Attributes will be different and can not be hard-coded.
DECLARE #Xml XML='<row>
<DeletedVal>
<row attribute1="value1" attribute2="value2"/>
</DeletedVal>
</row>';
SELECT x1.y.value('local-name(.)', 'VARCHAR(30)') AS [Key]
, x1.y.value('.', 'VARCHAR(MAX)') AS [Value]
FROM #Xml.nodes('/row/DeletedVal//#*') x1(y)
Output:
Key Value
------------------------------ ------
attribute1 value1
attribute2 value2
The following OPENXML approach needs fixing, where I am not sure how to get the attributes.
DECLARE #DocHandle INT
EXEC sp_xml_preparedocument
#DocHandle OUTPUT
, #Xml;
SELECT *
FROM OPENXML (#docHandle, N'/row/DeletedVal//#*')
WITH ([Key] VARCHAR(10) 'key' --- This line needs editing
, [Value] VARCHAR(10) '.')
EXEC Sp_xml_removedocument
#DocHandle;
Output:
Key Value
---------- ----------
NULL value1
NULL value2
As #Larnu correctly pointed out, Microsoft proprietary OPENXML and its companions sp_xml_preparedocument and sp_xml_removedocument are kept just for backward compatibility with the obsolete SQL Server 2000.
It is strongly recommended to re-write your SQL and switch it to XQuery. It is available in MS SQL Server starting from 2005 onwards.
I made some performance improvements to your T-SQL by removing the //#* (search for descendants everywhere down) from the .nodes() XQuery method.
DECLARE #Xml XML =
N'<row>
<DeletedVal>
<row attribute1="value1" attribute2="value2"/>
</DeletedVal>
</row>';
SELECT c.value('local-name(.)', 'VARCHAR(30)') AS [Key]
, c.value('.', 'VARCHAR(MAX)') AS [Value]
FROM #Xml.nodes('/row/DeletedVal/row/#*') AS t(c);
Output
+------------+--------+
| Key | Value |
+------------+--------+
| attribute1 | value1 |
| attribute2 | value2 |
+------------+--------+
Referring this link, I found the solution as below:
DECLARE #Xml XML='<row><DeletedVal><row attribute1="value1" attribute2="value2"/></DeletedVal></row>';
DECLARE #DocHandle INT
EXEC sp_xml_preparedocument
#DocHandle OUTPUT
, #Xml;
SELECT *
FROM OPENXML (#docHandle, N'/row/DeletedVal//#*')
WITH ([Key] VARCHAR(10) '#mp:localname'
, [Value] VARCHAR(10) '.')
EXEC Sp_xml_removedocument
#DocHandle;

XML Cdata format and variable input TSQL

DECLARE #TransactionId NVARCHAR(100)
DECLARE #TransactionDateTime DATETIME
--Setting Variable
SET #TransactionId= (SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID()))
SET #TransactionDateTime= GETDATE()
--Start the XML Selction
SELECT
1 AS Tag,
NULL AS Parent,
NULL AS 'Tag!1!',
NULL AS 'TransactionType!2!CollectSampling!cdata',
NULL AS 'TransactionID!2!TransactionId!cdata',
NULL AS 'TransactionDateTime!2!TransactionDateTime!cdata',
NULL AS 'ContainerName!2!Name!cdata',
NULL AS 'Make!2!Make!cdata',
NULL AS 'Model!2!Model!cdata',
NULL AS 'Price!2!Price!cdata',
NULL AS 'Type!2!Type!cdata'
Union ALL
SELECT
2 AS Tag,
1 AS Parent,
NULL,
'CollectSample',
#TransactionId,
#TransactionDateTime,
[Name] ,
[Make] ,
[Model] ,
[Price] ,
[Type]
from dbo.RepCar
FOR XML EXPLICIT, ROOT('Message')
The below is the output I would like to have but keep getting XML formats errors. Also just the Message is the parent
Would like output as below.I'm using variables to populate a couple of tags and CollectSample is static field.
<Message>
<TransactionType><![CDATA[CollectSamplingData]]></TransactionType>
<TransactionID><![CDATA[0CA4E46F-5143-498C-B1AC-F990FF70462E]]></TransactionID>
<TransactionDate><![CDATA[2020-01-10T14:20:30-05:00]]></TransactionDate>
<CName><![CDATA[Name]]></CName>
<MakeCar><![CDATA[Make]]></MakeCar>
<MakeModel><![CDATA[Model]]></MakeModel>
<DataValue><![CDATA[Price]]></DataValue>
<MakeType><![CDATA[Type]]></MakeType>
</Message>
declare #RepCar table
(
[Name] varchar(10),
[Make] varchar(10),
[Model] varchar(10),
[Price] money,
[Type] varchar(10)
);
insert into #RepCar
(
Name, Make, Model, Price, Type
)
values
('Car1', 'Make1', 'Model1', 100, 'Type1'),
('Car2', 'Make2', 'Model2', 200, 'Type2'),
('Car3', 'Make3', 'Model3', 300, 'Type3');
DECLARE #TransactionId NVARCHAR(100)
DECLARE #TransactionDateTime DATETIME
--Setting Variable
SET #TransactionId= (SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID()))
SET #TransactionDateTime= GETDATE()
--Start the XML Selction
/*
ElementName!TagNumber!AttributeName!Directive
AttributeName
Provides the name of the attribute to construct in the specified ElementName. This is the behavior if Directive is not specified.
!!!! If Directive is specified and it is xml, cdata, or element, this value is used to construct an element child of ElementName, and the column value is added to it.!!!!
*/
select 1 AS Tag,
0 AS Parent,
'CollectSamplingData' as 'Message!1!TransactionType!cdata',
#TransactionId as 'Message!1!TransactionID!cdata',
#TransactionDateTime as 'Message!1!TransactionDate!cdata',
[Name] as 'Message!1!CName!cdata',
[Make] as 'Message!1!MakeCar!cdata',
[Model] as 'Message!1!MakeModel!cdata',
[Price] as 'Message!1!DataValue!cdata',
[Type] as 'Message!1!MakeType!cdata'
from #RepCar --dbo.RepCar
FOR XML EXPLICIT, ROOT('Messages');

Error when loading date/time via xml SQL Server

SQL Server 2016
I am loding bulk records via xml. I have the following query:
DECLARE #xmlString VARCHAR(4000);
SET #xmlString = N'
<Customers>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<CreateDate>10/7/2016 7:31:06 AM</CreateDate>
</Customers>
';
DECLARE #xml XML;
SET #xml = CONVERT(XML, #xmlString);
INSERT INTO [test].dbo.[customers]
( [OrderID] ,
[CustomerID] ,
[CreateDate]
)
SELECT T.Customer.value('(OrderID)[1]', 'INT') AS OrderID ,
T.Customer.value('(CustomerID)[1]', 'nvarchar(20)') AS CustomerID ,
T.Customer.value('(CreateDate)[1]', 'DATETIME') AS CreateDate
FROM #xml.nodes('Customers') AS T ( Customer );
If I remove the CreateDate field, this will load just fine. However, if i leave the CreateDate field in, i receive this error:
Msg 241, Level 16, State 1, Line 35
Conversion failed when converting date and/or time from character string.
CreateDate is a DATETIME field.
Here is the table:
CREATE TABLE [dbo].[Customers](
[OrderID] [INT] NULL,
[CreateDate] [DATETIME] NOT NULL,
[CustomerID] [NVARCHAR](10) NULL
) ON [PRIMARY]
What conversion am I missing to load date/time into my table via xml? Thanks
In your comment you say I am creating the xml. How are you doing this?
In properly created XML date/time value ought to be ISO8601.
Your few lines of code show, that you do not think in XML. XML is not simple text with some extra characters...
Nevertheless your format is convertable with code 131 for dd/mm/yyyy or 101 for mm/dd/yyyy, but you should not do this!
DECLARE #xml XML=
N'
<Customers>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<CreateDate>10/7/2016 7:31:06 AM</CreateDate>
</Customers>
';
SELECT c.value('OrderID[1]','int') AS OrderID
,c.value('CustomerID[1]','nvarchar(100)') AS CustomerID
,CONVERT(DATETIME,c.value('CreateDate[1]','nvarchar(100)'),101) AS CreateDate
FROM #xml.nodes('Customers') AS A(c)
Better try it like this
DECLARE #xml2 XML=
N'
<Customers>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<CreateDate>2016-10-07T07:31:06</CreateDate>
</Customers>
';
SELECT c.value('OrderID[1]','int') AS OrderID
,c.value('CustomerID[1]','nvarchar(100)') AS CustomerID
,c.value('CreateDate[1]','datetime') AS CreateDate
FROM #xml2.nodes('Customers') AS A(c)
Use following if the XML date is in mm/dd/yyyy format
CONVERT(datetime, T.Customer.value('(CreateDate)[1]', 'nvarchar(50)'), 101) AS CreateDate
If the Date in XML is in some other format like dd/mm/yyyy - please visit below link to find out what should be placed instead of 101
https://msdn.microsoft.com/en-us/library/ms187928.aspx

Resources