How do I modify a xml attribute in a xml field of a Sql Server table - sql

I'm trying to update a XML column in a SQL Server table using the
XML.modify replace value of (XML DML)
With the below XML example, is there a way I can replace all vendorId with value 1 into another value? From the documentation in http://technet.microsoft.com/en-us/library/ms190675.aspx it looks like I need to specify the record index for that. But in my case, there would be multiple records within the xml and I would not know the order it would be in.
<LineItems>
<LineItem productId="48" invId="1573" quantity="1" id="1" vendorId="1022" price="1350.0000" cost="450.0000" discount="0" acqu="2" />
<LineItem productId="1" invId="0" quantity="1" id="2" vendorId="1" price="400" cost="0" discount="0" />
<LineItem productId="46" invId="1574" quantity="1" id="3" vendorId="1022" price="789.0000" cost="263.0000" discount="0" acqu="4" />
<LineItem productId="1" invId="0" quantity="1" id="4" vendorId="1" price="300" cost="0" discount="0" />
</LineItems>
Please advice.
Thanks!

You have to use a loop and update one value at a time.
while #XML.exist('/LineItems/LineItem[#vendorId = "1"]') = 1
set #XML.modify('replace value of (/LineItems/LineItem[#vendorId = "1"]/#vendorId)[1] with "2"' )
SQL Fiddle
A version that updates a XML column in a table would look like this.
while exists(
select * from T
where T.XMLColumn.exist('/LineItems/LineItem[#vendorId = "1"]') = 1
--and [some other condition]
)
begin
update T
set XMLColumn.modify('replace value of (/LineItems/LineItem[#vendorId = "1"]/#vendorId)[1] with "2"')
where T.XMLColumn.exist('/LineItems/LineItem[#vendorId = "1"]') = 1
--and [some other condition]
end
SQL Fiddle

If you need to replace a constant string to another one, I advise you yo use REPLACE function and perfom it on string.
DECLARE #XML XML /*your xml value*/
SELECT REPLACE(CONVERT(NVARCHAR(MAX),#XML),'vendor="1"','"vendor="2"')
In many cases it's much easier then do it in xml-style.

Related

T-SQL, get value from xml in a column

I have a table with an XML column (xmlCol) and I am trying to query a value from it.
Here's the xml.
<criteria>
<factor name="Rivers" title="Rivers">
<value dataType="Int32" value="1743" description="Wilson0" />
</factor>
<factor name="OptionalAffProperties" title="Include properties">
<value dataType="String" value="FishingModel" description="Fishing Model" />
</factor>
</criteria>
Here is a select to get the column. select xmlCol from MyTable
I am trying to return the value 1743 to a column called RiverID.
Mike
This should work:
SELECT
xmlCol.value('(//factor[#name="Rivers"]/value/#value)[1]', 'int') As RiverID
FROM
MyTable
value() Method (xml Data Type) - SQL Server | Microsoft Docs
XQuery Language Reference (SQL Server) - SQL Server | Microsoft Docs
To get the attribute value, you can query it like so:
select xmlCol.value('(/criteria/factor/value/#value)[1]', 'int') RiverID
from MyTable
You provide the xml path to the record you are looking for: (/criteria/factor/value
And then the attribute you need: /#value)[1].

Parsing XML in SQL without a namespace

The code will be self explanatory to the right person for this, but any questions please shout...
Thanks,
Dave
DECLARE #XML XML
SET #XML =
'<?xml version="1.0" encoding="utf-8"?>
<updates>
<versions>
<installer type="A" Xversion="101" iniSizeInBytes="22480" dataSizeInBytes="23396349" msiSizeInBytes="4732928" />
<installer type="B" Yversion="201" iniSizeInBytes="22480" dataSizeInBytes="116687353" msiSizeInBytes="5807616" webconfigModifierSizeInBytes="11800" />
<installer type="A" Xversion="102" iniSizeInBytes="22480" dataSizeInBytes="23396349" msiSizeInBytes="4732928" />
<installer type="B" Yversion="202" iniSizeInBytes="22480" dataSizeInBytes="116687353" msiSizeInBytes="5807616" webconfigModifierSizeInBytes="11800" />
</versions>
<update setNumber="1" XVersion="101" YVersion="201">
<detail Ref="1000">some detail info for 101 and 201</detail>
</update>
<update setNumber="2" XVersion="102" YVersion="202">
<detail Ref="1001">some detail info for 102 and 202</detail>
</update>
</updates>
'
SELECT
r.value('#ref','NVARCHAR(250)') as 'Ref', --This is wrong, but you can probably see i'm wanting the value of Ref, eg 1000 for line 1, 1001 for line 2
t.r.query('./detail').value('.','nvarchar(max)') as 'Detail'
FROM #XML.nodes('/updates/update') AS t(r);
You need detail element in value method to get the value in Ref attribute
SELECT
r.value('#Ref','NVARCHAR(250)') as 'Ref', -- It should be #Ref instead of #ref
r.query('.').value('.','nvarchar(max)') as 'Detail'
FROM #XML.nodes('/updates/update/detail') AS t(r);
Note : Elements and attributes in xml is case sensitive you cannot use #ref in query when xml attribute is Ref
Rextester Demo

Replace XML Data in SQL Server 2012

I have a request to replace the XML property with another tables column value. Currently I'm confused on how to proceed further. I did some investigation but none of the seems to be working for my scenario. Could someone help me out with this. Thanks in advance.
I have the below query
DECLARE #XML XML
SET #XML = '<LookupSyndicationExportProfileData Id="-1" Name="">
<LookupExportScopes IncludeAllLookup="False" IncludeAllLocale="False" GroupBy="ColumnName" FileFormat="Excel10">
<Locales>
<Locale PK_Locale="1" ShortName="English World Wide" LongName="" FK_Culture="0" FK_Region="0" FK_Lang="0" />
</Locales>
<LookupExportScope Id="0" Name="Brand" />
<LookupExportScope Id="1" Name="BrandColor" />
<LookupExportScope Id="2" Name="BrandType" />
</LookupExportScopes>
</LookupSyndicationExportProfileData>'
SELECT
'tblk_' + N.C.value('#Name', 'nvarchar(100)') NAME,
N.C.value('#Id', 'nvarchar(100)') Id,
ro.Pk_RST_Object
FROM
#XML.nodes('//LookupExportScope') N(C)
INNER JOIN
tb_RST_Object ro ON 'tblk_' + N.C.value('#Name','nvarchar(100)') = ro.Shortname
Below is the result of the above query.
So, I need to update my #XML variable with Id property to the PK_RST_Object value. Please let me know how shall I do this.

XML Output from SQL Server 2008

I am trying to create an XML output from SQL that has 3 nested statements but have pretty minimal experience in this area. The code I've written is below:
select
replace(replace(replace(
(
select ID as [#ID],
(select cast(Name as int) as [#Name],
(select num as [#Number],
from #tbl_new_claims_export
for xml path('Num'),root('Numbers'), type
)
from #tbl_new_claims_export
for xml path('LineItem'), type
)
from #tbl_new_claims_export
for XML PATH('Line'),ROOT('Lines')
),'><','>'+char(10)+'<'),'<Num', char(9)+'<Num'), '<Num>', char(9)+'<Num>') ;
I am trying to create an output that looks like this:
<Lines>
<Line ID ="1">
<LineItem Name ="Michael"/>
<Numbers>
<Num Number="24"</Num>
</Numbers>
</LineItem>
</Line>
For each Line, I want to see the Line, Name, and Number as shown above. However, it is showing multiple Names under each Line and then repeats the Number below. Can anybody help me troubleshoot this code?
Thanks.
Without sample data with 1:n examples and the expected output it is reading in the magic glass bulb...
Anyway, this
SELECT
1 AS [Line/#ID]
,'Michael' AS [LineItem/#Name]
,24 AS [Numbers/Num/#Number]
FOR XML PATH('Lines')
will produce exactly the output you specify:
<Lines>
<Line ID="1" />
<LineItem Name="Michael" />
<Numbers>
<Num Number="24" />
</Numbers>
</Lines>
If you need further help, please specify a minimal and reduced test scenario. Best would be a fiddle or some pasteable code like
DECLARE #tbl TABLE(ID INT, col1 VARCHAR(MAX)/*more columns*/);
INSERT INTO #tbl VALUES (1,'test1')/*more values*/

selecting an attribute from XML in SQL

Okay, I have a table that has a column called bdParameters, datatype is text. The data stored in the bdParameters column is XML saved as text.
The data goes like this:
<root>
<row statusID="ALL" subID="ALL" viewMaskFields="false" masID="219"
userID="13" prptyDate="08/19/2011" docID="21b15c9e-76a5-44ed-afbb-96b6df2cf881"
resmID="8806" leaID="6345" reshID="3560" doEmail="" emailFrom="" emailTo=""
emailMsg="penarands" emailSubject="" fieldList="1" fmtID="2" OptInCES="Yes"
SendVaiEmailCES="1" RPIPMCURL="blabla#blabla.com" />
<Custom>
<UpdateResidentLetter>
<Row Status="NOTPRINTED" Notes="Created from bulk lettersinterface" />
</UpdateResidentLetter>
</Custom>
</root>
I want to be able to select only the attribute emailMsg from that xml.
Is that possible? If so, how?
Use xml.value with the # symbol to get the attribute
declare #t table (col xml);
insert #t select '
<root><row statusID="ALL" subID="ALL" viewMaskFields="false" masID="219"
userID="13" prptyDate="08/19/2011" docID="21b15c9e-76a5-44ed-afbb-96b6df2cf881"
resmID="8806" leaID="6345" reshID="3560" doEmail="" emailFrom="" emailTo=""
emailMsg="penarands" emailSubject="" fieldList="1" fmtID="2" OptInCES="Yes"
SendVaiEmailCES="1" RPIPMCURL="lm-10-254-9-52.onesitedev.realpage.com" /><Custom>
<UpdateResidentLetter><Row Status="NOTPRINTED" Notes="Created from bulk letters
interface" /></UpdateResidentLetter></Custom></root>';
select col.value('(/root/row/#emailMsg)[1]','varchar(max)') emailMsg
from #t
-- result
penarands