Add node to XML using TRANSACT-SQL - sql-server

I've been struggling with this simple piece of code without result. I'm just trying to add a new node to an XML variable.
DECLARE #XML XML;
SET #XML = '<root>
<policyData>
<txtComentario />
<idRegProducto>76</idRegProducto>
<txtDuracion>24</txtDuracion>
</policyData>
</root>';
DECLARE #NODE XML;
SET #NODE = '<newNode>10</newNode>';
SET #XML.modify
('insert sql:variable("#NODE") as first
into (/root/policyData)[0]')
SELECT #XML;
There is no errors, but the new node is not showing in the output. Is there something that I must setup first before using XML in SQL Server? Any suggestion why this is not working?
Thanks in advance!

When you use [0] you are actually saying [position()=0]. The first node has position 1 so you should change the predicate to [1] if you want to insert the new node into the first occurrence of policyData.

Related

Xquery delete with Xpath from sql:variable

I am having Xpath to delete from XML in an VARCHAR(MAX) variable, but XML.modify('delete '+#MyXpath) give an error ,
The argument 1 of the XML data type method "modify" must be a string
literal.
DECLARE #myXML XML,
#MyXpath VARCHAR(MAX)
-- Processing of Xpaths for components needed to remove
-- Adding those in #XpathsToRemove
SELECT TOP(1) #MyXpath = [XPATH]
FROM #XpathsToRemove
SET #myXML.modify('delete '+#MyXpath)
Is there any way to remove those components with Xpath available in #MyXpath variable ?
-- Edit Example XML
DECLARE #myXML XML ='<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Dont forget me this weekend!</body>
</note>'
,#MyXpath VARCHAR(MAX) = '//note/from'
-- There are many Xpaths and dynamically generated with some processing so I don't want to hardcode Xpath there
SET #myXML.modify('delete '+#MyXpath)
--This doesn't works too
-- SET #myXML.modify('delete "sql:variable("MyXPath")"')
SELECT #myXML
Thanks guys, I got solution by EXEC to generate dynamic queries.
Following is link that solved my issue,
How to using for loop using XQuery to delete xml nodes [duplicate]
Solution,
DECLARE #str nvarchar(MAX)
SET #str = 'SET #MyXML.modify('+char(39)+'delete '+#MyXPath+'/*'+char(39)+'); '
EXEC sp_executesql #str, N'#MyXML xml output', #MyXML output

Get the value of each XML node and set it to a parameter

How to set a parameter in each XML nodes using SQL Server 2008?
I am new with SQL and I have XML data like this
Set #xml='<root><name>John </name><age>8</age></root>'
I need to set the value of node <name>, <age> in a parameter. For example:
Set #name='get value of node <name>'
Set #age='the value of <age>'
Is this possible? Thanks!
If I get this correctly you are getting parameters within an XML as key-value-pairs. What you try to achieve is to read the value into the fitting variable. Try it like this:
DECLARE #xml XML;
SET #xml='<root><name>John </name><age>8</age></root>';
DECLARE #name NVARCHAR(100);
DECLARE #age INT;
SET #name=#xml.value('(/root/name)[1]','nvarchar(max)');
SET #age =#xml.value('(/root/age)[1]','int');
SELECT #name,#age;
If you'd need to query the values from a variable name, you can use this:
DECLARE #nodeName NVARCHAR(100)='name';
SET #name=#xml.value('(/root/*[local-name()=sql:variable("#nodeName")])[1]','nvarchar(max)');
The central idea is to use an XQuery-expression (/root/*[local-name()=sql:variable("#nodeName")])[1] to pick the first node's value, where the element's name is like the given parameter

Insert into xml in sql using modify method

I have to modify the existing xml in a table field value.
Each row value has different xml tags like
1 row.
'<root><comments><comment>comments1</comment><comment>comments2</comment></comments></root>'
2 row .
'<Users><User><Name>MAK</Name></User><User><Name>DANNY</User></Users>'
I need to add a tag <Resource>some ID</Resource>
after the root node.
like '<Users>**<Resource>some ID</Resource>**<User><Name>comments1</Name></User><User><Name>comments2</User></Users>'
I have tried with the below code .
declare #xml xml
set #xml = '<root><comments><comment>comments1</comment><comment>comments2</comment></comments></root>'
declare #Note varchar(10)
declare #insertnode nvarchar(100)
set #insertnode='commeressd'
declare #mainnode varchar(50)
set #mainnode='(//root)[1]'
set #Note = 'comment3'
SET #xml.modify('insert <Resource>{xs:string(sql:variable("#insertnode"))}</Resource> as first into {xs:string(sql:variable("#mainnode"))}')
select #xml
the expression after
into
is giving the error
XQuery [modify()]: Syntax error near '{'
..how do we specify this into expression also dynamically.
Any help would be appreciated.
You can use /*[1] to find the "first" root node where you want the insert to happen.
declare #xml xml
set #xml = '
<root>
<comments>
<comment>comments1</comment>
<comment>comments2</comment>
</comments>
</root>'
declare #insertnode nvarchar(100)
set #insertnode='ResourceID'
set #xml.modify('insert element Resource {sql:variable("#insertnode")} as first into /*[1]')
select #xml
Result:
<root>
<Resource>ResourceID</Resource>
<comments>
<comment>comments1</comment>
<comment>comments2</comment>
</comments>
</root>

Delete nodes with certain value from XML using TSQL

I'm trying to parse a piece of XML and remove nodes that contain certain values. I know how to remove them if the value is exact, but I want to use something like a "contains".
This works to delete exactly:
update #XML set data.modify('delete //Message[text() = "customer has deleted their account"]')
But I want to delete where the "Message" node just contains the text, something like:
update #XML set data.modify('delete //Message[contains(text(), "customer")]')
However this returns the error:
XQuery [#XML.data.modify()]: 'contains()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
Try
update #XML set data.modify('delete //Message[text()][contains(.,"customer")]')
to delete the <message/> element and its contents
update #XML set data.modify('delete //Message//text()[contains(.,"customer")]')
to delete the <message/> element's contents.
Example here http://msdn.microsoft.com/en-us/library/ms178026.aspx
declare #XML xml = '
<Root>
<Sub>
<Record>
<Guid>aslkjflaksjflkasjfkljsd</Guid>
</Record>
<Record>
<Guid>opqiwuerl;kasdlfkjawop</Guid>
</Record>
</Sub>
</Root>'
declare #Guid varchar(30) = 'aslkjflaksjflkasjfkljsd'
set #XML.modify('delete /Root/Sub/Record[Guid = sql:variable("#Guid")]')
Reference
https://dba.stackexchange.com/questions/40039/how-to-return-xml-node-ordinal-or-delete-node-based-on-element-value

T-SQL, XQuery Invalid Column

I'm just learning XQUERY and trying to accomplish what I thought would be very simple. Here's my T-SQL code:
DECLARE #XML xml
set #xml = '<resultsets><AppVersion>13.0</AppVersion></resultsets>'
-- Code below is wrong
select
ResultSets.AppVersion.query('AppVersion').value('.', 'varchar(100)') as AppVersion
from #XML.nodes('/resultsets/AppVersion') ResultSets(AppVersion)
I cannot figure out exactly how to query that inner element, appversion. I'm not getting any errors, but I'm unable to return that 13.0 within the appversion inner-element. Can someone please help?
You've got one AppVersion too many. This returns your 13.0 :
DECLARE #XML xml
set #xml = '<resultsets><AppVersion>13.0</AppVersion></resultsets>'
-- Code below is right
select
ResultSets.AppVersion.value('.', 'varchar(100)') as AppVersion
from #XML.nodes('/resultsets/AppVersion') ResultSets(AppVersion)
Your nodes method already gets down to the AppVersion nodes, so from there you don't need a further query, just the value.
If you only want one row as a result there is no need to use nodes.
DECLARE #XML xml
set #xml = '<resultsets><AppVersion>13.0</AppVersion></resultsets>'
select #XML.value('(/resultsets/AppVersion)[1]', 'varchar(100)') as AppVersion

Resources