Update XML stored in a XML column in SQL Server - sql-server

I have a sample table in SQL Server 2012. I am running some queries against but the .modify() XQuery method is executing but not updating.
Here is the table
For this just trying to update settings to 'NewTest'
This will execute but nothing is updating! Thanks for any help!

Since there is a XML namespace (xmlns:dev="http://www.w3.org/2001/XMLSchema") in your XML document, you must inlcude that in your UPDATE statement!
Try this:
;WITH XMLNAMESPACES(DEFAULT 'http://www.w3.org/2001/XMLSchema')
UPDATE XmlTable
SET XmlDocument.modify('replace value of (/Doc/#Settings)[1] with "NewTest"')
WHERE XmlId = 1

You should declare a namespace in your update syntax .Try the below syntax
Declare #Sample table
(xmlCol xml)
Insert into #Sample
values
('<dev:Doc xmlns:dev="http://www.w3.org/2001/XMLSchema"
SchemaVersion="0.1" Settings="Testing" Ttile="Ordering">
<Person id="1">
<FirstName>Name</FirstName>
</Person>
</dev:Doc>')
Select * from #Sample
Update #Sample
SET xmlCol.modify(
'declare namespace ns="http://www.w3.org/2001/XMLSchema";
replace value of (/ns:Doc/#Settings)[1]
with "NewTest"')
Select * from #Sample

Related

Getting xml as result from exec stored procedure

I'm trying to get the result of an executed stored procedure to be retrieved as a XML of the table the result is shown as originally.
What I'm trying to do is somthing like this.
exec dbo.StoredProcedure FOR XML RAW, ROOT ('root_name').
Lets say exec dbo.StoredProcedure returns the table in the Stored Procedure,
I want the FOR XML RAW, ROOT ('root_name') to return the XML value of that whole result.
How do I achieve this In SQL server?
One method is to insert the proc results into a temp table or variable using INSERT...EXEC and then select from that table with the desired FOR XML query:
DECLARE #results AS TABLE(col1 int, col2 int);
INSERT INTO #results EXEC dbo.StoredProcedure;
SELECT col1, col2
FROM #results
FOR XML RAW, ROOT ('root_name');
As per this question, you should not select from the stored procedure. Also if you dig into that question, you will find a link to an interesting article describing options you have with stored procedures.
If I were you I would either return an XML with an output parameter, or insert-exec into a table and then query it with for xml.

Update a table row with XML (SQL Server)

I have a xml file below generated using
SELECT * FROM case WHERE ticketNo=#ticketNo FOR XML RAW,
ELEMENTS
The XML looks like this:
<row>
<ticketNo>1</ticketNo>
<caller>name</caller>
<category>3</category>
<service>4</service>
<workgroup>5</workgroup>
</row>
And I update my table using this query with the same with some value changed
UPDATE case
set caller = xmldoc.caller
set category = xml.category
from OpenXml(#idoc, '/row')
with (ticketNo VARCHAR(50)'./ticketNo',
caller VARCHAR(50) './caller',
category VARCHAR(50) './category') xmldoc
where dbo.tb_itsc_case.ticketNo = xmldoc.ticketNo
Is it possible to update the table without specifying the individual column?
You can not do an update without specifying the columns and you can not get data from XML without specifying what nodes to get the data from.
If you can use the "new" XML data type that was introduced in SQL Server 2005 you can do like this instead.
declare #XML xml =
'<row>
<ticketNo>1</ticketNo>
<caller>name</caller>
<category>3</category>
<service>4</service>
<workgroup>5</workgroup>
</row>'
update [case] set
[caller] = #XML.value('(/row/caller)[1]', 'varchar(50)'),
category = #XML.value('(/row/category)[1]', 'varchar(50)')
where
ticketNo = #XML.value('(/row/ticketNo)[1]', 'varchar(50)')
I was able to use this to update 1 row in a table. It requires you to have all fields specified in the XML. It replaces the existing row with the one specified in the XML.
I wish I could figure out how to do it for only the columns that are in the XML. I work on projects where the fields in the table change frequently and it requires re-specifying all the procedures to list out the column names.
create procedure Update_TableName (#xml xml) as
DECLARE #handle INT
EXEC sp_xml_preparedocument #handle OUTPUT, #xml
DECLARE #ID varchar(255)
SELECT #ID = ID FROM OPENXML (#handle, '/data', 2) WITH TableName
if exists (select 1 from TableName where ID = #ID)
delete from TableName where ID = #ID
Insert into TableName
SELECT * FROM OPENXML (#handle, '/data', 2) WITH TableName
EXEC sp_xml_removedocument #handle
XML:
<data>
<ID>9999</ID>
<Column1>Data</Column1>
<Column2>Data</Column2>
<Column3>Data</Column3>
</data>

sql server 2005 xquery read xml type

I have declared a #xmldata as xml. How to read it? I tried
declare #xmldata as xml
set #xmldata = <root><row ename='abc' eid='1'/></root>
SELECT #XMLDATA
but it returned an error. I want to fetch eid column from the above xml type.
Try this:
declare #xmldata as xml
set #xmldata = '<root><row ename="abc" eid="1"/></root>'
SELECT
#xmldata.value('(/root/row/#eid)[1]', 'int') AS 'EID'
Update: if you need to select from your table and extract something from the XML column, use this approach:
SELECT
tbl.ID,
tbl.XmlColumn.value('(/root/row/#ename)[1]', 'varchar(25)') AS 'EName'
FROM
dbo.YourTable tbl
WHERE
(...some condition here...)

How to convert a SQL Server result set to XML after the fact?

Is there a way to cause the result set of a SQL Server stored procedure (or any result set, after the fact) to be encoded in XML format?
I want the result set to be encoded in XML as if the FOR XML RAW clause was used during selection.
However the complex stored procedure logic and its internal SELECT statements should not be modified to return XML because the procedure is used for its standard/non-XML result set most of the time.
Update: Emphasis on the fact I'm looking for an answer in the SQL Server environment - the
results should be returned as if SQL Server has directly encoded them itself, as XML, just like it does when using the built-in XML features like the FOR XML clause.
You would insert the data from the SP into a temp table, then select from that FOR XML
This won't work if the SP itself already does a INSERT .. EXEC SPROC because you cannot nest them
Working examples
use tempdb;
create proc giveme
as
select a = 1, b = GETDATE()
union all
select 2, b = '20100101'
Using INSERT.. EXEC
declare #t table (a int, b datetime)
insert #t
exec giveme
select * from #t for xml raw
Using OPENQUERY
exec sp_addlinkedserver 'localhost'
exec sp_serveroption #server = 'localhost'
,#optname = 'DATA ACCESS'
,#optvalue = 'TRUE'
select *
from openquery(localhost, 'exec tempdb..giveme')
for xml raw
You could try using OPENROWSET in cooperation with FOR XML to do the transformation.
By 'after the fact', do you mean still within the SQL Server environment? Or are you talking about a client program?
Within SQL, you could probably write a sproc that acts as a wrapper for your other sprocs, along these lines. The wrapper sproc would handle the FOR XML work.
In .NET, there are a number of ways to do this.
You can try inserting the result set from the stored procedure into a table variable( or temporary table) and selecting the table rows with the FOR XML clause.
Here is an example:
DECLARE #MyDataTable AS TABLE ( col1 int,...., colN int)
Make sure that the #MyDataTable has the same columns as the stored procedure result set(s).
INSERT INTO #MyDataTable
EXECUTE mysp_GetData #param1=value,....,#paramN;
SELECT * FROM #MyDataTable
FOR XML AUTO

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