Xml query resulting in error in sql server - sql

This is my xml query
declare #XML xml
set #XML=
'<ROOT>
<Customers>
<CustomerId>1111</CustomerId>
<CompanyName>Sean Chai</CompanyName>
<City>NY</City>
</Customers>
<Customers>
<CustomerId>1112</CustomerId>
<CompanyName>Tom Johnston</CompanyName>
<City>LA</City>
</Customers>
<Customers>
<CustomerId>1113</CustomerId>
<CompanyName>Institute of Art</CompanyName>
</Customers>
</ROOT>';
SELECT
R.Node('.').value('(/Customers/CustomerId/.)[1]','varchar(100)') AS CustomerID,
R.Node('.').value('(/Customers/CompanyName/.)[1]','varchar(100)') AS CompanyName
FROM #XML.nodes('/ROOT/Customers') R(Node)
But its giving error:
Msg 4121, Level 16, State 1, Line 20
Cannot find either column "R" or the user-defined function or aggregate "R.Node", or the name is ambiguous.
i searched but couldn't get R.node Thing pls somebody guide me onthis !
and i'm not understanding #XML.nodes('/ROOT/Customers') R(Node) ?
what is its use in query!

Change the query like this and try
SELECT
R.Node.value('(CustomerId/.)[1]','varchar(100)') AS CustomerID,
R.Node.value('(CompanyName/.)[1]','varchar(100)') AS CompanyName
FROM #XML.nodes('/ROOT/Customers') R(Node)
First of all you have syntax error in your query. You have aliase to your resultant table as R(Node), then you cannot specifiy the path as R.Node(.).
Secondly the path that you mentioned in your query is wrong (/Customers/CustomerId/.)

Related

Extract xml value from table SQL Server

I am trying to extract value from xml in table.PFB sample xml.
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfKeyValue xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<KeyValue>
<Key>[#Id#]</Key>
<Value>354005</Value>
</ArrayOfKeyValue>
I am trying below script and it is not working.
SELECT
CAST(CAST(([KeyWordValues]) AS ntext) AS XML).value('(/ArrayOfKeyValue/KeyValue[1])', 'nvarchar(max)')
FROM
Table
I'm getting this error :
Msg 2389, Level 16, State 1, Line 1
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
Please note XML is saved as varchar in the database.
Please help. Thanks in advance
Thanks alot for help. I got it working.
SELECT cast(cast(([KeyWordValues]) as ntext) as
xml).value('(/ArrayOfKeyValue/KeyValue/Value)[1]', 'nvarchar(max)')
FROM Table

SQL query for XML data

I have a SQL Server database table with a column called XML that contains XML data which is structured like this:
<Item xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://test/data">
<Roots>
<Root>
<Name>Field Name</Name>
<Value>Field Value</Value>
</Root>
<Root>
<Name>Field Name</Name>
<Value>Field Value</Value>
</Root>
</Roots>
I want to use T-SQL to get the Value where Name = Total. I have tried the following but it isn't returning any data:
SELECT [XML]
FROM [BusinessAccount]
WHERE [XML].value('(/Root/Name)[13]', 'VARCHAR(MAX)') LIKE '%Total%'
If anyone could tell me where I've gone wrong?
You are missing the required WITH XMLNAMESPACES for your XML and the path is incorrect.
If you want to bring back rows where the 13th element consists of the text Total you can use the below.
WITH XMLNAMESPACES (DEFAULT 'http://test/data')
SELECT [XML]
FROM [BusinessAccount]
WHERE 1 = [XML].exist('(/Item/Roots/Root/Name)[13][text() = "Total"]')
Otherwise you can add the WITH XMLNAMESPACES to your original query and fix the path there too.
You need to specify namespaces. You can then match <Name> and <Value> pairs and extract the contents of <Value> like so:
SELECT NameNode.value('declare namespace x="http://test/data"; (../x:Value)[1]', 'varchar(100)')
FROM [BusinessAccount]
CROSS APPLY [XML].nodes('declare namespace x="http://test/data"; //x:Root/x:Name') AS n(NameNode)
WHERE NameNode.value('.', 'varchar(100)') = 'Total'
Demo on db<>fiddle

SQL Server XQuery.modify "Syntax error near ':', expected '}'"

Table Test.User contains one field "Details" which is in XML type.
The Details value of user which Id is 1024 is in the following format:
<Details>
<Name>Kevin</Name>
<Age>23</Age>
</>Details>
I try to insert a new node "Address" into this xml value likes this:
UPDATE Test.User
SET Details.modify('insert <Address>{0:c0}</Address> into (/Details)[1]')
WHERE Id = 1024
But error occurs, please help advise on it.
"Syntax error near ':', expected '}'"
You need to escape these types of {0:c0} markup characters with CDATA section
DECLARE #DETAILS XML ='<Details>
<Name>Kevin</Name>
<Age>23</Age>
</Details>'
SELECT #DETAILS
SET #DETAILS.modify('insert <Address><![CDATA[{0:c0}]]></Address> into (/Details)[1]')
SELECT #DETAILS
Then the result will be like
<Details>
<Name>Kevin</Name>
<Age>23</Age>
<Address>{0:c0}</Address>
</Details>

Select values from XML in SQL

I need to select values from an XML document. These values are stored as childnodes as follows:
<customers>
<customer>
<kunnr>1</kunnr>
<kdgrp>2</kdgrp>
</customer>
<customer>
<kunnr>2</kunnr>
<kdgrp>2</kdgrp>
</customer>
</customers>
I need to select the values of kunnr and kdgrp for every customer node. I expect a result like this:
kunnr kdgrp
1 2
2 2
What I tried so far:
SELECT #xml.query('/customers/customer/kunnr') AS KUNNR,
#xml.query('/customers/customer/kdgrp') AS KDGRP
This results in one row with two colums containing XML:
KUNNR KDGRP
<kunnr>1</kunnr><kunnr>2</kunnr> <kdgrp>2</kdgrp><kdgrp>2</kdgrp>
Another try:
SELECT C.value('/kunnr/text()','nvarchar(10)') as KUNNR,
C.value('/kdgrp/text()','nvarchar(10)') as KDGRP
from #xml.nodes('/customers/customer') AS T(C);
This resulted in the following error message:
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
Maybe something like this:
DECLARE #xml XML
SET #xml='<customers>
<customer>
<kunnr>1</kunnr>
<kdgrp>2</kdgrp>
</customer>
<customer>
<kunnr>2</kunnr>
<kdgrp>2</kdgrp>
</customer>
</customers>'
And then a query like this:
SELECT
c.value('kunnr[1]', 'nvarchar(10)') AS kunnr,
c.value('kdgrp[1]', 'nvarchar(10)') AS kdgrp
FROM
#xml.nodes('//customers/customer') as t(c)
This will give you this result:
kunnr kdgrp
1 2
2 2
I had a problem related to extracting values from T-SQL XML and found an issue that may help others. When retrieving data with: .value('(/root/subnode)[1]', 'varchar(max)') that call would not retrieve data but the following call did: .value('(//subnode)[1]', 'varchar(max)'). Note that the working version replaced the root node with a /. The problem with the first call seemed to be that the root node came with a specification of an xml namespace like &< root xmlns="http://www..." &> and to get the .value call to return data I needed to get past the specification of the namespace which was causing things to fail for some reason.

Modify xml element name in SQL Server

How to change element name from Cust to Customer?
<Cust id="1">
<Name>aaaaaaaaaa</Name>
<Desc>bbbbbbbbbb</Desc>
</Cust>
When I'm using following statement
select #myXml.query('/node()[1]/node()') for xml raw('Customer')
sql removes attributes
<Customer>
<Name>aaaaaaaaaa</Name>
<Desc>bbbbbbbbbb</Desc>
</Customer>
Try this:
SELECT
#myXml.value('(/Cust/#id)[1]', 'int') AS '#id',
#myXml.query('/node()[1]/node()')
FOR XML PATH('Customer')
Gives me an output of:
<Customer id="1">
<Name>aaaaaaaaaa</Name>
<Desc>bbbbbbbbbb</Desc>
</Customer>
With the FOR XML PATH, you can fairly easily "restore" that attribute that gets lost in the conversion.
You could use replace:
replace(replace(#YourXml, '<Cust id', '<Customer id)', '</Cust>', '</Customer>')
This is fairly safe, as < is not valid as data in XML, it would appear as < or an ASCII or UNICODE sequence.