SQL Query + Google Geocode Response XML - sql-server

I have the XML response from the Google Geocoding API stored in a SQL Server XML column. Can someone help me with a query that will return all rows where the XML contains > 1 result?
e.g.
<GeocodeResponse>
<status>OK</status>
<result></result> <!-- more than one result is present -->
<result></result>
<result></result>
</GeocodeResponse>
So something like this gives me the first result:
SELECT XmlResponse.query('/GeocodeResponse/result') FROM Locations
But I'm not sure where to go from here...

You can use the exist() method of the XML data type to check if there exist a second <result> node.
select *
from Locations
where XmlResponse.exist('GeocodeResponse/result[2]') = 1
Test the query here. https://data.stackexchange.com/stackoverflow/q/101340/xmlcolumn-exist

Related

Getting blank result when parsing xml in MS SQL SERVER

I am trying to parse XML data stored in a SQL server table. I have tried using the following code (adjusted to remove personal information and to show the setup) but it is returning a blank. Is there some way to do this to get my result? The expected result should be
Your claim has been rejected on 2022/10/22. Your claim has been
rejected. Reason: This is an inactive scheme. Please contact the
Client Service Centre on 123456789 or at email#mail.com for
assistance.
declare #tempxml as table (xmlstr varchar(max));
insert into #tempxml
values (replace('<?xml version="1.0" encoding="UTF-8"?>
<hb:MedicalAidMessage xmlns:hb="address.co.za/messaging"
Version="6.0.0">
<Claim>
<Details>
<Responses>
<Response Type="Error">
<Code>6</Code>
<Desc>Your claim has been rejected on 2022/10/22. Your claim has been rejected. Reason: This is an inactive scheme. Please contact the Client Service Centre on 123456789 or at email#mail.com for assistance.</Desc>
</Response>
</Responses>
</Details>
</Claim>
</hb:MedicalAidMessage> ',':',''))
declare #XMLData xml
set #XMLData = (select * from #tempxml)
select [Reason] = n.value('Desc[1]', 'nvarchar(2000)')
from #XMLData.nodes('/hbMedicalAidMessage/Claim/Details/Reponses/Response') as a(n)
Thanks
Consider the following queries which demonstrate two ways to access the namespace-referenced elements correctly:
select [Reason] = Response.value('(Desc/text())[1]', 'nvarchar(2000)')
from #XMLData.nodes('
declare namespace foo = "address.co.za/messaging";
/foo:MedicalAidMessage/Claim/Details/Responses/Response') as a(Response);
with xmlnamespaces('address.co.za/messaging' as foo)
select [Reason] = Response.value('(Desc/text())[1]', 'nvarchar(2000)')
from #XMLData.nodes('/foo:MedicalAidMessage/Claim/Details/Responses/Response') as a(Response);
Note that the namespace prefix foo in the queries does not match the hb prefix in the original XML. It's not the prefixes that need to match the XML but the namespaces they reference which, in all cases, is address.co.za/messaging.

Creating XML Schema for Bulk Load to SQL Server - Child Element Describes Parent

I have an XML document that I'm working to build a schema for in order to bulk load these documents into a SQL Server table. The XML I'm focusing on looks like this:
<Coverage>
<CoverageCd>BI</CoverageCd>
<CoverageDesc>BI</CoverageDesc>
<Limit>
<FormatCurrencyAmt>
<Amt>30000.00</Amt>
</FormatCurrencyAmt>
<LimitAppliesToCd>PerPerson</LimitAppliesToCd>
</Limit>
<Limit>
<FormatCurrencyAmt>
<Amt>85000.00</Amt>
</FormatCurrencyAmt>
<LimitAppliesToCd>PerAcc</LimitAppliesToCd>
</Limit>
</Coverage>
<Coverage>
<CoverageCd>PD</CoverageCd>
<CoverageDesc>PD</CoverageDesc>
<Limit>
<FormatCurrencyAmt>
<Amt>50000.00</Amt>
</FormatCurrencyAmt>
<LimitAppliesToCd>Coverage</LimitAppliesToCd>
</Limit>
</Coverage>
Inside the Limit element, there's a child LimitAppliesToCd that I need to use to determine where the Amt element's value actually gets stored inside my table. Is this possible to do using the standard XML Bulk Load feature of SQL Server? Normally in XML I'd expect that the element would have an attribute containing the "PerPerson" or "PerAcc" information, but this standard we're using does not call for that.
If anyone has worked with the ACORD standard before, you might know what I'm working with here. Any help is greatly appreciated.
Don't know exactly what you are talking about, but this is a solution to get the information out of your XML.
Assumption: Your XML is already bulk-loaded into a declared variable #xml of type XML:
A CTE will pull the information out of your XML. The final query will then use PIVOT to put your data into the right column.
With a fitting table's structure the actual insert should be simple...
WITH DerivedTable AS
(
SELECT cov.value('CoverageCd[1]','varchar(max)') AS CoverageCd
,cov.value('CoverageDesc[1]','varchar(max)') AS CoverageDesc
,lim.value('(FormatCurrencyAmt/Amt)[1]','decimal(14,4)') AS Amt
,lim.value('LimitAppliesToCd[1]','varchar(max)') AS LimitAppliesToCd
FROM #xml.nodes('/root/Coverage') AS A(cov)
CROSS APPLY cov.nodes('Limit') AS B(lim)
)
SELECT p.*
FROM
(SELECT * FROM DerivedTable) AS tbl
PIVOT
(
MIN(Amt) FOR LimitAppliesToCD IN(PerPerson,PerAcc,Coverage)
) AS p

Update SQL Server table using XML data

From my ASP.Net application I am generating XML and pass it as input data to stored procedure as below,
<Aprroval>
<Approve>
<is_nb_approved>false</is_nb_approved>
<is_approved>true</is_approved>
<is_submitted>true</is_submitted>
<UserId>35</UserId>
<ClientId>405</ClientId>
<taskDate>2015-05-23T00:00:00</taskDate>
</Approve>
<Approve>
<is_nb_approved>false</is_nb_approved>
<is_approved>true</is_approved>
<is_submitted>true</is_submitted>
<UserId>35</UserId>
<ClientId>405</ClientId>
<taskDate>2015-05-24T00:00:00</taskDate>
</Approve>
</Approval>
And below is my stored procedure,
create procedure UpdateTaskStatus(#XMLdata XML)
AS
UPDATE [TT_TaskDetail]
SET
is_approved=Row.t.value('(is_approved/text())[1]','bit'),
is_nb_approved=Row.t.value('(is_nb_approved/text())[1]','bit'),
is_submitted=Row.t.value('(is_submitted/text())[1]','bit')
FROM #XMLdata.nodes('/Aprroval/Aprrove') as Row(t)
WHERE user_id = Row.t.value('(UserId/text())[1]','int')
AND client_id = Row.t.value('(ClientId/text())[1]','int')
AND taskdate = Row.t.value('(taskDate/text())[1]','date')
But when I execute this stored procedure, I am getting return value as 0 and no record is getting updated. Any suggestions welcome.
You have 2 errors in your xml:
First is nonmatching root tags.
Second, more important, you are quering nodes('/Aprroval/Aprrove'), but inner tag is Approve not Aprrove.
Fiddle http://sqlfiddle.com/#!3/66b08/3
Your outer tags do not match. Your opening tag says, "Aprroval" instead of "Approval". Once I corrected that, I was able to select from the XML without issue.

extract xml element from database using sql query

Hello I have the following xml structure within a database table column :
DECLARE #Response XML =
'<star:ShowInfo xmlns="http://www.starstandard.org/STAR/5"
xmlns:ns2="http://www.openapplications.org/oagis/9"
xmlns:star="http://www.starstandard.org/STAR/5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" releaseID="5.1.5"
xsi:noNamespaceSchemaLocation="">
<ShowDataArea>
<ServiceInfo>
<SVPlanInfo>
<AKStatus>
<Code>Error</Code>
<STText xsi:type="ns2:TextType">E12143 - Please fetch me from this xml </STText>
</AKStatus>
</SVPlanInfo>
</ServiceInfo>
</ShowDataArea></star:ShowInfo>'
In the above xml I need to fetch the STText value which is
E12143 - Please fetch me from this xml . Can anyone point me on how I can do it ?
I tried the following but it doesnt seem to work :
;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema' as xsd,
'http://www.w3.org/2001/XMLSchema-instance' as xsi)
SELECT #Response.value('(/xsd:Response)[1]','nvarchar(500)') as ExceptionMessage
What a pain.
remove:
xmlns="http://www.starstandard.org/STAR/5"
It is not a sql issue, but rather namespace-getting-confused issue.
Its heplful totake SQL out the equation sometimes, by testing some place like
http://xpath.online-toolz.com/tools/xpath-editor.php.

SQL XML query assistance

I've got a table in a SQL Server 2008 database with an nvarchar(MAX) column containing XML data. The data represents search criteria. Here's what the XML looks like for search criteria with one top-level "OR" group containing one single criterion and a nested two-criterion "AND" group.
<?xml version="1.0" encoding="utf-16"?>
<SearchCriterionGroupArgs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SingleCriteria>
<SearchCriterionSingleArgs>
<Operator>Equals</Operator>
<Value>test</Value>
<FieldIDs>
<int>1026</int>
<int>478</int>
</FieldIDs>
<EntityID>92</EntityID>
</SearchCriterionSingleArgs>
</SingleCriteria>
<GroupCriteria>
<SearchCriterionGroupArgs>
<SingleCriteria>
<SearchCriterionSingleArgs>
<Operator>GreaterThan</Operator>
<Value>2010-01-23</Value>
<FieldIDs>
<int>1017</int>
</FieldIDs>
<EntityID>92</EntityID>
</SearchCriterionSingleArgs>
<SearchCriterionSingleArgs>
<Operator>LessThan</Operator>
<Value>2013-01-23</Value>
<FieldIDs>
<int>1018</int>
</FieldIDs>
<EntityID>92</EntityID>
</SearchCriterionSingleArgs>
</SingleCriteria>
<GroupCriteria />
<EntityID>92</EntityID>
<LogicalOperator>AND</LogicalOperator>
</SearchCriterionGroupArgs>
</GroupCriteria>
<EntityID>92</EntityID>
<LogicalOperator>OR</LogicalOperator>
</SearchCriterionGroupArgs>
Given a an input set of FieldID values, I need to search the table to find if there are any records whose search criteria refer to one of those values (these are represented in the "int" nodes under the "FieldIDs" nodes.)
By running this query:
select CAST(OptionalConditions as xml).query('//FieldIDs')
from tblMyTable
I get the results:
<FieldIDs>
<int>1026</int>
<int>478</int>
</FieldIDs>
<FieldIDs>
<int>1017</int>
</FieldIDs>
<FieldIDs>
<int>1018</int>
</FieldIDs>
(currently there's only one record in the table with xml data in it.)
But I'm just getting started with this stuff and I don't know what the notation would be to check those lists for the existence of any of an arbitrary set of FieldIDs. I don't need to retrieve any particular nodes, just true or false for whether the input field IDs are referenced anywhere in the search.
Thanks for your help!
Edit: using Ranon's solution, I got it working using a query like this:
SELECT *
FROM myTable
WHERE CAST(OptionalConditions as xml).exist('//FieldIDs/int[.=(1019,111,1018)]') = 1
Fetch all FieldIDs and compare them with the set id IDs to check against. XQuery's =-operator compares in a set-based semantics, so if one of the IDs on the left side equal on one the right, this expression will evaluate to true.
//FieldIDs/int = (42, 478)
As "478" is a FieldID, this query will return true. "42" is one not available.
I'm not sure about whether you will be able to cast the result to some sql-server-boolean-type as I haven't got one running, but you will easily be able to try out yourself.
If you're also interested in the nodes contained, you could use this query:
//FieldIDs/int[. = (42,478)]

Resources