Replace XML Data in SQL Server 2012 - sql

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.

Related

Query xml using xquery in SQL Server 2016

I have my XML in following format:
<resultset xmlns="qm_system_resultset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<result>
<result_id>F5</result_id>
<exception>NO</exception>
<recurring_count>0</recurring_count>
<defect>NO</defect>
<unresolved>NO</unresolved>
<exception_approval />
<comments />
<exception_expiration>3000-01-01</exception_expiration>
<exception_stat_only>NO</exception_stat_only>
<result_data>
<phraseprefix>rx</phraseprefix>
<phrasenumber>0001</phrasenumber>
<languagedesc>Khmer</languagedesc>
<englishphrase> each time.</englishphrase>
<phrasedesc> គ្រាប់ក្នុងមួយដង។</phrasedesc>
<qm_translatedphrase>day.</qm_translatedphrase>
</result_data>
</result>
<result>
<result_id>26</result_id>
<exception>NO</exception>
<recurring_count>0</recurring_count>
<defect>NO</defect>
<unresolved>NO</unresolved>
<exception_approval />
<comments />
<exception_expiration>3000-01-01</exception_expiration>
<exception_stat_only>NO</exception_stat_only>
<result_data>
<phraseprefix>hold</phraseprefix>
<phrasenumber>0001</phrasenumber>
<languagedesc>Hmong</languagedesc>
<englishphrase>Hold than 160.</englishphrase>
<phrasedesc>Tsis 160.</phrasedesc>
<qm_translatedphrase>Do not use </qm_translatedphrase>
</result_data>
</result>
Using TSQL/XML query how do I achieve this RESULT
[phraseprefix][phrasenumber]
rx 0001
hold 0001
...
I tried the following query, but I got null values for both the columns:
DECLARE #input XML = (SELECT result_xml
FROM QM_Data_Audit.QM_Package.test_results
WHERE result_id = 2446338)
SELECT
resultset.value('(phraseprefix)[1]', 'varchar(max)') AS 'phrasenumber',
resultset.value('(phrasenumber)[1]', 'int') AS 'phrasenumber'
FROM #input.nodes('/resultset/result/result_data') AS List(resultset)
My apologies if the question is asked previously, I am new to querying XML.
Appreciate your help.
Your xml has a namespace declared so you need to provide this when querying it. In this example this can be acheived with the WITH XMLNAMESPACES statement:
DECLARE #input XML = (SELECT result_xml
FROM QM_Data_Audit.QM_Package.test_results
WHERE result_id = 2446338);
WITH XMLNAMESPACES(DEFAULT 'qm_system_resultset')
SELECT
resultset.value('(phraseprefix)[1]', 'varchar(max)') AS 'phrasenumber',
resultset.value('(phrasenumber)[1]', 'varchar(max)') AS 'phrasenumber'
FROM #input.nodes('/resultset/result/result_data') AS List(resultset)
You'll want to set the data type for phrasenumber to varchar as well to preserve the leading 0s if you need them.

Extracting data from XML Nodes

I am testing this simple script and just wondering why it didn't work.
DECLARE #myDoc xml
DECLARE #ProdID int
SET #myDoc =
'<Datatype xmlns="V8_0_1" id="113" name="PF_CleaningMode" hdl="47/4/SB8_3-910-8243-19/0/113" odobjid="915">
<Datatypevalue id="2" name="Intermittent" />
<Datatypevalue id="1" name="Continuous" />
<Datatypevalue id="0" name="Off" />
</Datatype>'
SET #ProdID = #myDoc.value('(Datatype/#id)[1]', 'int' )
SELECT #ProdID
Hope you can assist. Thanks.
You're just simply ignoring the default XML namespace that's defined on your <Datatype> node:
<Datatype xmlns="V8_0_1" id="113" name="PF_CleaningMode"
**************
You need to include that in your query!
Like this:
;WITH XMLNAMESPACES(DEFAULT 'V8_0_1')
SELECT #myDoc.value('(Datatype/#id)[1]', 'INT')
and you'll get the expected output of
113

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

Select multiple values in XML file and concatenation them with xQuery

I have the following XML:
<items>
<item value="1"/>
<item value="2"/>
<item value="4"/>
</items>
and I would like to select all item value and concatenate them like this - see below - with XQuery :
1.2.4
Any ideas?
Thanks in advance.
There are two parts to your question:
getting values out of xml
concatenating multiple values together
The second part of your question has been covered off very nicely in the answers to this question.
In terms of getting the values out of your xml, try the below:
-- Your xml variable
DECLARE #xml AS XML = '<items>
<item value="1"/>
<item value="2"/>
<item value="4"/>
</items>'
-- Example of selecting the values into rows
SELECT
item.value('.', 'int')
FROM
#xml.nodes('/items/item/#value') as T1(item)
-- Use your favourite/'best for your circumstance' method of
-- concatenating the rows into one string
-- see https://stackoverflow.com/q/194852/1208914 for other ways
SELECT
item.value('.', 'varchar(50)') + ' ' as 'data()'
FROM
#xml.nodes('/items/item/#value') as T1(item)
for xml path('')
I've put the code above into a sql fiddle that you can access and play with here: http://sqlfiddle.com/#!6/d41d8/18144/0
Using XQuery you can simply select the values using XPath and join them together using a dot.
string-join(/items/item/#value, '.')

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

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.