This question already has answers here:
SQL Server Xml query with multiple namespaces
(3 answers)
Closed 3 years ago.
The problem
I need to take data from XML files provided by another application. These XMLs contain data that is required to be inserted into tables for a database for a different application.
The problem is this, I can't get the values out of the XML file. I keep getting blank/null values instead.
I am using SQL Server 2014 Management Studio.
What I've tried
I've looked into how to read an XML and have that placed into a table. I've gone as far as looking at tutorials that work. But, whenever I try to apply the same process to my tables and using my XML data I keep getting blank values.
Some help would be appreciated as I have been looking into this for a day and researching how to approach this using MS SQL. And I cannot for the life of me understand why I keep getting nulls.
The XML
<DistributionOrder xmlns="a-url">
<Date>2019-03-07T14:38:00</Date>
<Order_Number>ACME01</Order_Number>
<Comment/>
<Status>Active</Status>
<Lines>
<Line>
<Order_Line_Number>1</Order_Line_Number>
<Product>22</Product>
<Status_Line>Active</Status_Line>
<Comment_Line/>
<Location>ENT_78</Location>
</Line>
</Lines>
</DistributionOrder>
The query
DECLARE #xmlData XML;
INSERT INTO dbo.XMLwithOpenXML(XML_data)
SELECT *
FROM OPENROWSET(BULK 'C:\test_file.xml', SINGLE_BLOB) AS ImportSource;
SELECT * FROM XMLwithOpenXML;
SELECT
element.value('(Order_Line_Number/text())[1]', 'nvarchar(80)') AS Order_Line_Number,
element.value('(Product/text())[1]', 'nvarchar(80)') AS Product
FROM
XMLwithOpenXML
CROSS APPLY
XML_data.nodes('DistributionOrder/Lines/Line') AS DO(element)
GO
What I expect
Order_Line_Number | Product
------------------+----------
1 | 22
What I Get
Order_Line_Number | Product
------------------+----------
|
Figured out that the,
<DistributionOrder xmlns="a-url">
</DistributionOrder>
was the problem. I deleted the xmlns="a-url" from the xml and found that my code is working.
Discovered that you can use
;WITH XMLNAMESPACES(DEFAULT 'a-url')
To take the namespace into account.
Related
I'm trying to put together a report for a badge program. Some the data for custom fields we created are stored in a single column in the table as XML. I need to return a couple of the items in there to the report and am having a hard time getting the proper syntax to get it to parse out.
Aside from the XML, the query itself is simple:
SELECT
Person1.firstName
,Person1.lastName
,Person1.idNumber
,Person1.idNumber2
,Person1.idNumber3
,Person1.status
,Person1.customdata
FROM
Person1
the field "customdata" is the XML field that I need to pull Title, and 2 different dates out of. This is what the XML looks like:
<person1_7:CustomData xmlns:person1_7="http://www.badgepass.com/Person1_7">
<Title>IT Director</Title>
<Gaming_x0020_Level>Level 1</Gaming_x0020_Level>
<Gaming_x0020_Issue_x0020_Date>2021-02-18T12:00:00Z</Gaming_x0020_Issue_x0020_Date>
<Gaming_x0020_Expire_x0020_Date>2022-02-18T12:00:00Z</Gaming_x0020_Expire_x0020_Date>
<Betting_x0020_Level>Level 1</Betting_x0020_Level>
<Betting_x0020_Issue_x0020_Date>2021-02-18T12:00:00Z</Betting_x0020_Issue_x0020_Date>
<Betting_x0020_Expire_x0020_Date>2022-02-18T12:00:00Z</Betting_x0020_Expire_x0020_Date>
<BadgeType>Dual Employee</BadgeType>
<Gaming_x0020_Status>TEMP</Gaming_x0020_Status>
<Betting_x0020_Status>TEMP</Betting_x0020_Status>
</person1_7:CustomData>
I have tried a couple of different methods trying to follow the advice from How to query for Xml values and attributes from table in SQL Server? and then tried declaring a XML namespace with the following query:
WITH XMLNAMESPACES ('http://www.badgepass.com/Person1_7' as X)
SELECT
Person1.firstName
,Person1.lastName
,Person1.idNumber
,Person1.idNumber2
,Person1.idNumber3
,Person1.status
,Person1.customdata.value('(/X:person1_7:customdata/X:Title)[1]', 'varchar(100)') AS Title
FROM
Person1
So far all of my results keep returning "XQuery [Person1.customData.value()]: ")" was expected.
" I'm assuming I have a syntax issue that I'm overlooking as I've never had to manipulate XML with SQL before. Thank you in advance for any help.
Please try the following solution.
Notable points:
XQuery .nodes() method establishes a context so you can access any
XML element right away without long XPath expressions.
Use of the text() in the XPath expressions is for performance
reasons.
SQL
-- DDL and sample data population, start
DECLARE #person1 TABLE (firstname varchar(50), customdata xml);
INSERT INTO #person1(firstname, customdata) VALUES
('John', '<person1_7:CustomData xmlns:person1_7="http://www.badgepass.com/Person1_7">
<Title>IT Director</Title>
<Gaming_x0020_Level>Level 1</Gaming_x0020_Level>
<Gaming_x0020_Issue_x0020_Date>2021-02-18T12:00:00Z</Gaming_x0020_Issue_x0020_Date>
<Gaming_x0020_Expire_x0020_Date>2022-02-18T12:00:00Z</Gaming_x0020_Expire_x0020_Date>
<Betting_x0020_Level>Level 1</Betting_x0020_Level>
<Betting_x0020_Issue_x0020_Date>2021-02-18T12:00:00Z</Betting_x0020_Issue_x0020_Date>
<Betting_x0020_Expire_x0020_Date>2022-02-18T12:00:00Z</Betting_x0020_Expire_x0020_Date>
<BadgeType>Dual Employee</BadgeType>
<Gaming_x0020_Status>TEMP</Gaming_x0020_Status>
<Betting_x0020_Status>TEMP</Betting_x0020_Status>
</person1_7:CustomData>');
-- DDL and sample data population, end
WITH XMLNAMESPACES ('http://www.badgepass.com/Person1_7' as person1_7)
SELECT firstName
, c.value('(Title/text())[1]', 'VARCHAR(100)') AS Title
, c.value('(Gaming_x0020_Issue_x0020_Date/text())[1]', 'DATETIME') GamingIssueDate
FROM #person1
CROSS APPLY customdata.nodes('/person1_7:CustomData') AS t(c);
Output
+-----------+-------------+-------------------------+
| firstName | Title | GamingIssueDate |
+-----------+-------------+-------------------------+
| John | IT Director | 2021-02-18 12:00:00.000 |
+-----------+-------------+-------------------------+
I'm a beginner when it comes to SQL and have no experience with XML so I'm after a little bit of help.
At the moment I am looking at a single table and just using the query below
select
name,
convert(xml, convert(varbinary(max), orders)) ClientOrders
from client;
In the second columns of SQL output, I have a very lengthy bit of XML similar to the example below. I've used "..." just to skip over some of the output and give a general idea.
Name
ClientOrders
Client1
<report ... ><QueryParameter></QueryParameter Name = "#hello1"><commandtext> ...<value>Example1</value>....<value>Example2</value>...<value>Example3</value>...</commandtext></report>
Client2
<report ... ><QueryParameter></QueryParameter Name = "#hello2"><commandtext> ...<value>Example4</value>....<value>Example5</value>...<value>Example6</value>...</commandtext></report>
I have this for a lot of rows and this output is so long that it exceeds the Excel cell character limit. I'm only looking for the values Example1 through to Example6 in the example given above. Is there an SQL command I can run to get the above string between the open and close value?
I am using SSMS version 18.9.1
Cheers
This question already has an answer here:
Query Data from XML
(1 answer)
Closed 5 years ago.
I have a table in an Oracle 12c Database that contains a XML Type Column and i need to extract a value from this Column.
Here an example of this Column's content:
<AbcMsg xmlns="http://example.org/SCL/CommonTypes">
<Msg>
<Pmnt>
<swif:SWIFT MT="202" xmlns:swif="urn:abc/scl/SWIFT" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<swif:Header>
<swif:Input_Output_Identifier>O</swif:Input_Output_Identifier>
<swif:Sender_BIC>XXXXXXXXXXX</swif:Sender_BIC>
<swif:Receiver_BIC>XXXXXXXXXXX</swif:Receiver_BIC>
<swif:Message_Priority>NORM</swif:Message_Priority>
<swif:User_Header>
<swif:Message_User_Reference>XXXXXXXXXXXXXXXXX</swif:Message_User_Reference>
</swif:User_Header>
<swif:Original_Swift>
<swif:Message>DATA TO BE EXTRACTED</swif:Message>
</swif:Original_Swift>
<swif:Create_Date_Time>2016-07-28T15:45:00</swif:Create_Date_Time>
<swif:Msg_ID>POFu7yCXHoN</swif:Msg_ID>
<swif:Sequence_Number>248600</swif:Sequence_Number>
<swif:Session_Number>6184</swif:Session_Number>
</swif:Header>
<swif:Data xsi:type="swif:Data_202">
<swif:F20>
<swif:Sender_s_Reference>POFu7yCXHoN</swif:Sender_s_Reference>
</swif:F20>
<swif:F21>
<swif:Related_Reference>XXXXXXXXXXX</swif:Related_Reference>
</swif:F21>
<swif:F32A>
<swif:Currency>USD</swif:Currency>
<swif:Amount>156020000</swif:Amount>
<swif:Date>2016-07-28</swif:Date>
</swif:F32A>
<swif:Cdrt_F58a_F59a>
<swif:Account>174208531</swif:Account>
<swif:Identifier_Code>XXXXXXXXX</swif:Identifier_Code>
</swif:Cdrt_F58a_F59a>
</swif:Data>
</swif:SWIFT>
</Pmnt>
<Extn/>
</Msg>
</AbcMsg>
I need to retrieve the Value of <swif:Original_Swift>. I've tried the function EXTRACT(xml_column, '/AbcMsg/Msg/Pmnt') but it keeps returning null.
Any clue on how to do that???
Thanks in Advance.
Try xmltable or xmlquery. You have to declare defult and swif namesapce;
select * from xmltable(XMLNAMESPACES('urn:abc/scl/SWIFT' as "swif", default 'http://example.org/SCL/CommonTypes') , '/AbcMsg/Msg/Pmnt/swif:SWIFT/swif:Header/swif:Original_Swift' passing xmltype(your_xml_here));
I have a query that uses FOR XML RAW, ELEMENTS to return a SELECT query as a structured XML document. However, when I get the result using a TSQLDataSet by using Fields[0].Value, the result is different from what I see when I run the query in SQL Server Management Studio.
What I see in the result from the TSQLDataSet:
customerIdфname၄governmentNumberไdebtorAddress1ไdebtorAddress2ไdebtorAddress3ไdebtorAddress4ࡄpostCodeୄcontactNameՄphonë́faxൄcustomerSinceՄtermsلactiveไcurrentBalanceلDebtorခŁ䄁ഃӤ
What I see in the result in SSMS:
<Debtor>
<customerId>C0E449E5B2C </customerId>
<name>New Customer 2 </name>
<governmentNumber> </governmentNumber>
<debtorAddress1>Address Line 1 </debtorAddress1>
<debtorAddress4>Address Line 4 </debtorAddress4>
<postCode>1234 </postCode>
<phone>1234567890 </phone>
<fax>1234567890 </fax>
<customerSince>2013-06-10T18:16:06.213</customerSince>
<terms>M </terms>
<active>true</active>
<currentBalance>0.0000</currentBalance>
</Debtor>
Is there a particular way it should be executed to get the right result?
AFAIK this is a DbExpress limitation. I know how overcome this, but using ADO (the returned data must be requested using a special parametrized object and a set of ADO streams). However you can use a workaround converting the XML data to a string in the server side sorrounding the sentence with a select (subquery) or just using a simple CAST statement.
For example if you sentence is like so
SELECT Foo, Bar FROM FooTable FOR XML RAW, ELEMENTS
you can rewrite to
SELECT (SELECT Foo, Bar FROM FooTable FOR XML RAW, ELEMENTS)
or you can rewrite to (use a CAST VARCHAR or NVARCHAR)
SELECT CAST( (SELECT Foo, Bar FROM FooTable FOR XML RAW, ELEMENTS) AS VARCHAR(MAX))
and finally
Retrieve the result like this
SQLDataSet1.Fields[0].AsString
This question already has answers here:
TSQL 2005, XML DML - Update Two Values at once?
(3 answers)
Updating multiple XML nodes using T-SQL [duplicate]
(1 answer)
Closed 8 years ago.
I'm using SQL Server and have Table with XML column. My procedure for insert has input parameter XML document. Is there any way how could I update already existing XML in my table?
This is my OLD XML in my table:
<weather Location="Paris, France">
<forecast>
<description>Sky is clear</description>
<Date>2013-09-19</Date>
<MinTemp>13</MinTemp>
<MaxTemp>20</MaxTemp>
<Humidity>78</Humidity>
<Pressure>1024</Pressure>
<Windspeed>3</WindSpeed>
</forecast>
<forecast>
<description>Sky is clear</description>
<Date>2013-09-20</Date>
<MinTemp>14</MinTemp>
<MaxTemp>21</MaxTemp>
<Humidity>75</Humidity>
<Pressure>1020</Pressure>
<Windspeed>1</WindSpeed>
</forecast> .... 10 times this forecast
</weather>
This is my new one:
<weather Location="Paris, France">
<forecast>
<description>Sky is clear</description>
<Date>2013-09-19</Date>
<MinTemp>14</MinTemp>
<MaxTemp>21</MaxTemp>
<Humidity>70</Humidity>
<Pressure>1000</Pressure>
<Windspeed>5</WindSpeed>
</forecast>
<forecast>
<description>Sky is clear</description>
<Date>2013-09-20</Date>
<MinTemp>17</MinTemp>
<MaxTemp>24</MaxTemp>
<Humidity>68</Humidity>
<Pressure>1024</Pressure>
<Windspeed>3</WindSpeed>
</forecast> .... 10 times this forecast
</weather>
What I want now is to update my old XML with values I read from new one. I know I have to somehow go trough my OLD XML, I think I could do that with ...while(exist) and modify, but how to read value I need from my new XML, how to read let's say data for September 19th, and update September 19th in old XML, then read data for September 20th, then update September 20th in old XML etc etc...?
Thanks for help...
You may try likethis:-
update tbl1
set myXml.modify('replace value of (/weather/forecast/..)[1]
with concat(string(sql:column("columnname")), "value")')
where myXml.exist('/weather/forecast/..') = 1 //some condition