Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sql query xml values returning NULL

I'm not experienced with the xml structure and need a start-point to how I can retrieve the values from xml structure below.

I fetch the xml from a webservice using a stored-procedure and store to a table "StockInfoXML" Field in table holding the xml is XML_Url of type xml.

<string xmlns="http://www.webserviceX.NET/">
  <StockQuotes>
    <Stock>
      <Symbol>ENGI.PA</Symbol>
      <Last>13.53</Last>
      <Date>5/23/2017</Date>
      <Time>12:37pm</Time>
      <Change>+0.06</Change>
      <Open>13.45</Open>
      <High>13.59</High>
      <Low>13.40</Low>
      <Volume>1524437</Volume>
      <MktCap>32.95B</MktCap>
      <PreviousClose>13.47</PreviousClose>
      <PercentageChange>+0.48%</PercentageChange>
      <AnnRange>10.77 - 15.20</AnnRange>
      <Earns>-0.23</Earns>
      <P-E>N/A</P-E>
      <Name>ENGIE</Name>
    </Stock>
  </StockQuotes>
</string>

I've tried a couple of things but keep returning null or nothing.

declare @X XML;

SELECT
@X = XML_Url
FROM dbo.StockExchangeInfoXML

SELECT 
x.s.value('(StockQuotes/Stock/Symbol)[1]', 'nvarchar(50)') AS [Symbol]
FROM @X.nodes('./StockQuotes/Stock') AS x(s);

Anyone who can get me started? Thanks.

like image 495
FGR Avatar asked May 24 '17 11:05

FGR


People also ask

How do I fix NULL in SQL?

There are two ways to replace NULL with blank values in SQL Server, function ISNULL(), and COALESCE(). Both functions replace the value you provide when the argument is NULL like ISNULL(column, '') will return empty String if the column value is NULL.

Can SQL read XML?

SQL Server lets you retrieve data as XML by supporting the FOR XML clause, which can be included as part of your query. You can use the FOR XML clause in the main (outer) query as well as in subqueries. The clause supports numerous options that let you define the format of the XML data.

What if subquery returns NULL?

For a scalar subquery: If the subquery returns no rows, the result of the scalar subquery is NULL . If the subquery returns more than one row, it is an error. If the subquery returns one row, the result is the value of the query's (only) column for that row.


1 Answers

Your xml includes a namespace xmlns="http://www.webserviceX.NET/", which is the default namespace. You must either declare it or use a wildcard for the prefix.

With XML there are some best practices:

  • Be as specific as possible
  • Only forward navigation
  • Important If the creation of the XML is under your control change the date and time format to ISO8601. Your formats are culture specific and can easily lead to conversion errors on different systems. Best was a combined value like <DateAndTime>2017-05-23T12:37:00</DateAndTime>

For your issue there are several approaches:

DECLARE @xml XML=
N'<string xmlns="http://www.webserviceX.NET/">
  <StockQuotes>
    <Stock>
      <Symbol>ENGI.PA</Symbol>
      <Last>13.53</Last>
      <Date>5/23/2017</Date>
      <Time>12:37pm</Time>
      <!--more elements -->
    </Stock>
  </StockQuotes>
</string>';

--Best approach: XMLNAMESPACES to declare the default namespace

WITH XMLNAMESPACES(DEFAULT 'http://www.webserviceX.NET/')
SELECT @xml.value(N'(/string/StockQuotes/Stock/Symbol/text())[1]',N'nvarchar(max)');

--Implicit namespace declaration:

SELECT @xml.value(N'declare namespace ns="http://www.webserviceX.NET/";
                   (/ns:string/ns:StockQuotes/ns:Stock/ns:Symbol/text())[1]',N'nvarchar(max)');

--Not recommended in most cases, but good for lazy people :-D

SELECT @xml.value(N'(//*:Symbol)[1]',N'nvarchar(max)');

--If you want to read more values of the same level, you can use .nodes to set the current node to ...<Stock>.

WITH XMLNAMESPACES(DEFAULT 'http://www.webserviceX.NET/')
SELECT st.value('(Symbol/text())[1]',N'nvarchar(max)')
      ,st.value('(Last/text())[1]',N'decimal(10,4)')
      --more nodes 
FROM @xml.nodes(N'/string/StockQuotes/Stock') AS A(st);
like image 136
Shnugo Avatar answered Sep 24 '22 17:09

Shnugo