selecting individual xml node using SQL - sql-server

I have a large XML note with many nodes.
is there a way that I can select only a single node and all of its contents from the larger XML?
i am using sql 2005

You should use the query() Method if you want to get a part of your XML.
declare #XML xml
set #XML =
'
<root>
<row1>
<value>1</value>
</row1>
<row2>
<value>2</value>
</row2>
</root>
'
select #XML.query('/root/row2')
Result:
<row2>
<value>2</value>
</row2>
If you want the value from a specific node you should use value() Method.
select #XML.value('(/root/row2/value)[1]', 'int')
Result:
2
Update:
If you want to shred your XML to multiple rows you use nodes() Method.
To get values:
declare #XML xml
set #XML =
'
<root>
<row>
<value>1</value>
</row>
<row>
<value>2</value>
</row>
</root>
'
select T.N.value('value[1]', 'int')
from #XML.nodes('/root/row') as T(N)
Result:
(No column name)
1
2
To get the entire XML:
select T.N.query('.')
from #XML.nodes('/root/row') as T(N)
Result:
(No column name)
<row><value>1</value></row>
<row><value>2</value></row>

Related

Can't read a property value from XML

I'm trying to get the value from the property Success but I can't, I don't know where I'm wrong.
This is my code
DECLARE #Response VARCHAR(8000) = '<?xml version="1.0" encoding="utf-8"?>
<Result xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/">
<Success>true</Success>
</Result>'
DECLARE #xml TABLE (
Content XML
)
INSERT INTO #xml
SELECT CAST(#Response AS XML)
SELECT
Content.value('(/Result/Success)[1]', 'BIT')
FROM #xml
The property Success is bool type
I'm trying with different scope types (nvarchar, varchar, bit, etc..)
This is what I expecting
or
Please try the following solution.
Notable points:
It is always better to use XML data type instead of the VARCHAR(..) for XML
data.
All XML elements are bound to the default namespace even if we don't
see it explicitly. That's why we need to specify it via
XMLNAMESPACES clause.
It is always better to use text() in the XPath expressions for XML
elements for performance reasons. Peculiarity of the MS SQL Server.
It is possible to omit XML prolog declaration completely. SQL Server
doesn't store it.
SQL
DECLARE #Response XML = '<?xml version="1.0" encoding="utf-8"?>
<Result xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/">
<Success>true</Success>
</Result>';
DECLARE #xml TABLE (Content XML);
INSERT INTO #xml
SELECT #Response;
;WITH XMLNAMESPACES (DEFAULT 'http://tempuri.org/')
SELECT result = Content.value('(/Result/Success/text())[1]', 'BIT')
FROM #xml;
Output
result
1

The argument 1 of the XML data type method "query" must be a string literal

I have data in xml format in SQL Server. Now I am trying to find out single record based on my query. I am putting my code below,
declare #xml xml
declare #ID varchar
set #ID = '1'
set #xml = '
<row>
<Id>1</Id>
<name>OM</name>
</row>
<row>
<Id>2</Id>
<name>JAI</name>
</row>
<row>
<Id>2</Id>
<name>JAGDISH</name>
</row>
'
When I am executing my query, then it gives me a proper result (xml node):
Select #xml.query('/row[Id="1"]');
But When I am concatenating #ID to query, then it gives me an error:
Select #xml.query('/row[Id='+ #ID +']');
The error is:
The argument 1 of the XML data type method "query" must be a string literal.
You will need the sql:variable() XQuery extension function to refer to a variable. This function (quote from the link) "exposes a variable that contains a SQL relational value inside an XQuery expression".
Select #xml.query('/row[Id=sql:variable("#ID")]');
You could use dynamic SQL:
IF TRY_PARSE(#ID AS INT) IS NULL
THROW 50000, 'ID is not integer',1;
DECLARE #sql NVARCHAR(MAX) = 'Select #xml.query(''/row[Id=<placeholder>]'')';
SET #sql = REPLACE(#sql, '<placeholder>', #Id);
EXEC sp_executesql #sql, N'#xml XML', #xml;
Rextester Demo
Warning!
Be aware that you should always check user input.

Parsing Non-Standard XML in TSQL

I need help parsing this XML in TSQL:
<Settings>
<Setting ERName="CAPTURE_MODE_ID" Value="9" />
<Setting ERName="VEHICLE_TYPE" Value="7" />
</Settings>
I would like to return the values as such:
Capture_Mode_Id Vehicle_Type
9 7
SQL Fiddle
declare #XML xml
set #XML = '
<Settings>
<Setting ERName="CAPTURE_MODE_ID" Value="9" />
<Setting ERName="VEHICLE_TYPE" Value="7" />
</Settings>'
select #XML.value('(/Settings/Setting[#ERName = "CAPTURE_MODE_ID"]/#Value)[1]', 'int') as CAPTURE_MODE_ID,
#XML.value('(/Settings/Setting[#ERName = "VEHICLE_TYPE"]/#Value)[1]', 'int') as VEHICLE_TYPE
Results:
| CAPTURE_MODE_ID | VEHICLE_TYPE |
|-----------------|--------------|
| 9 | 7 |
You need to perform two logical steps as best I can tell:
Parse the XML - i.e. get a result set from it.
Pivot the result set.
To get a result set from the XML, use the OPENXML function - something like the following...
DECLARE #idoc int, #doc varchar(1000);
-- the XML document
SET #doc ='
<ROOT>
<Settings>
<Setting ERName="CAPTURE_MODE_ID" Value="9" />
<Setting ERName="VEHICLE_TYPE" Value="7" />
</Settings>
</ROOT>';
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #idoc OUTPUT, #doc;
-- Execute a SELECT statement that uses the OPENXML rowset provider.
SELECT *
FROM OPENXML (#idoc, '/ROOT/Settings/Setting', 1)
WITH (ERName varchar(20), Value varchar(20));
..., which yields the following results:
ERName Value
--------------- -----
CAPTURE_MODE_ID 9
VEHICLE_TYPE 7
To pivot the result set without aggregation, consider the ideas presented to this end in a CALSQL blog post.

Query XML parameter in SQL

This seemed like a great idea on Friday afternoon but I'm having a bit of trouble. I've not used SQL XML querying before so I may of just done something incredibly stupid. Basically I want to pass a series of strings to query a table into a Stored Procedure.
I thought about this for a bit, considered using a CSV and then decided to attempt to do this using XML. So My XML looks like:
<Root>
<string>value</string>
<string>value</string>
<string>value</string>
<string>value</string>
</Root>
I'm passing this into a stored proc as an XML value type:
CREATE PROCEDURE usp_UpdateHotelImages
-- Add the parameters for the stored procedure here
#hotelID int,
#imageIDs xml
AS
BEGIN
so I want to shred the XML into a table of strings.
My SQL looks like this:
SELECT Child.value('(string)[1]', 'varchar(200)')
FROM #imageIDs.nodes('/Root/') AS N(Child))
But I keep getting the error message XQuery [nodes()]: Syntax error near '<eof>', expected a "node test".
I may well be doing something incredibly stupid here so any help will be gratefully received.
Update
I've broken it down into a single query to help:
DECLARE #imageIDs xml
SET #imageIDs = '<Root>
<string>value</string>
<string>value</string>
<string>value</string>
<string>value</string>
</Root>'
SELECT Child.value('(string)[1]', 'varchar(200)')
FROM #imageIDs.nodes('/Root/') AS N(Child)
The problem is the last / in the nodes function.
SELECT Child.value('(string)[1]', 'varchar(200)')
FROM #imageIDs.nodes('/Root') AS N(Child)
or alternatively
SELECT Child.value('(.)[1]', 'varchar(200)')
FROM #imageIDs.nodes('/Root/*') AS N(Child)
Depending on what you're trying to achieve.
The error is because of trailing / in your nodes expressions. It should just be /Root.
BTW, I think you are looking for a SELECT to return the values as a table which is achieved by the following:
DECLARE #imageIDs XML
SELECT #imageIDs = '
<Root>
<string>value</string>
<string>value2</string>
<string>value3</string>
<string>value4</string>
</Root>'
SELECT
Child.value('(.)[1]', 'varchar(200)')
FROM #imageIDs.nodes('/Root/string') AS N(Child)
Results:
value
value2
value3
value4
(4 row(s) affected)

How do I replace an XML Node value?

I need to replace 2 XML nodes, both postcodes with their correct value. How do I accomplish this in SQL 2005. The XML is in an XML column.
<customer><postcode>P22 2XH</postcode></customer>
with IP22 2XH
Regards
Rob
Working example to update xml node in a table
create table xml (xml xml);
insert xml values('<customer name="John"><postcode>P22 2XH</postcode></customer>');
insert xml values('<customer name="Doe"><postcode>P22 2XH</postcode></customer>');
insert xml values('<customer name="Jane"><postcode>P9 2XH</postcode></customer>');
UPDATE xml
SET xml.modify('
replace value of (//customer/postcode[text()="P22 2XH"]/text())[1]
with "IP22 2XH" ');
select * from xml;
If you had multiple postcode nodes PER xml-record-column, then you can use the below. SQL Server only allows one xml node replacement per modify, so you need to loop it.
create table xml (salesperson varchar(100), portfolios xml);
insert xml values('jim','
<customer name="John"><postcode>P22 2XH</postcode></customer>
<customer name="Doe"><postcode>P22 2XH</postcode></customer>
<customer name="Jane"><postcode>P9 2XH</postcode></customer>');
insert xml values('mary','
<customer name="Joe"><postcode>Other</postcode></customer>
<customer name="Public"><postcode>P22 2XH</postcode></customer>');
while exists (
select * from xml
cross apply portfolios.nodes('//customer/postcode[text()="P22 2XH"]') n(c))
UPDATE xml
SET portfolios.modify('
replace value of (//customer/postcode[text()="P22 2XH"]/text())[1]
with "IP22 2XH" ');
;
select * from xml

Resources