SQL Server Stored Procedure XML can't get node right - sql-server

I have this query here:
SELECT [Job_No] as '#Key',
(
)
FOR XML PATH('Job_No'), ROOT('Root')
and it returns like so:
<Root>
<Job_No Key="ORC0023">
</Job_No>
</Root>
How do I get it like so:
<Root>
<Key>ORC0023</Key>
</Root>

try this:
SELECT [Job_No] as 'Key' FROM Jobs
FOR XML PATH(''), root ('Root');
working fiddle

Related

XQuery Delete all unnecessary nodes T-SQL

Could you help me please with succh problem. I have an XML like:
<Root attr1="val1">
<El1><Child1/></El1>
<El2><Child2/></El2>
...
<ElN><ChildN/></ElN>
</Root>
I need to delete with T-SQL all nodes but node. So I don't know all nodes of the XML-documetn but if that docuemnt has node I need to delete all other nodes but . So the result must be:
<Root attr1="val1">
<El2><Child2/></El2>
</Root>
I thought about getting xml.query('(root/el2)[1]) to a new xml and then wrapping it with root element from the origin xml (somewhow). But if there is the way to modify origin xml?
When dealing with XML where all of the elements are properly closed you could use the query() XML function to perform an XQuery like the following:
declare #xml xml = '<Root attr1="val1">
<El1><Child1a/></El1>
<El1><Child1b/></El1>
<El2><Child2a/></El2>
<El2><Child2b/></El2>
<ElN><ChildNa/></ElN>
<ElN><ChildNb/></ElN>
</Root>';
select #xml.query('
for $root in /Root return
<Root>
{$root/#*}
{$root/El2[1]}
</Root>
');
This returns the XML output:
<Root attr1="val1"><El2><Child2a /></El2></Root>

Trying to query XML Data - node has a space in it

I am trying to learn how to work with xml files and data in SQL Server and I'm trying to query an xml file but nothing is returned.
Here is the xml data:
<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="AdmissionsByPCP" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="AdmissionsByPCP" xsi:schemaLocation="AdmissionsByPCP http://10.xxx.x.xx/ReportServer_NameofReportServer?%2FHl%20C%20Syst%20Reports%2health%2FAdmissBy&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID=h0iz5ijxgt2vdl45g3pjfs45&rc%3ASchema=True">
<Tablix2>
<Details_Collection>
<Details PCPCarrier="DoctorsName">
<Subreport1>
<Report Name="PCPAdmitSubReport">
<Tablix5 Textbox5="79">
<Details_Collection>
<Details Textbox37="Discharge Dx Code: ICDCode" Textbox89="Admit Dx Code: ICDCode" LOS="4" DischargeDate="07/10/2017" AdmitDate="07/06/2017" Hospital="Hospital Name" MemberName="Name" DOB="1/1/2019" AdmissionType="Inpatient" MemberNo="12345" Auth="321*I" Status="Close" AdmissionID="00001" LobName="Medicare" CarrierName="CarrierName"/>
</Details></Details_Collection></Tablix5></Report></Subreport1></Details></Details_Collection></Tablix2></Report>
Here is the query I'm using:
Declare #XMLData as XML
Set #XMLData=(
Select bulkcolumn
FROM OPENROWSET (Bulk '\Directory\AdmissionsByPCP.xml',
Single_Blob) a)
Select
#XMLData.value('(/Root/Report/Tablix2/Detail_Collections/DetailsPCPCarrier) [1]', 'varchar(max)') PCP
The query returns null and I don't know why. Is it because there is a space in the node (<Details PCPCarrier>) and if so how do I work around that?
You have misunderstood how XML works. This is the node you are looking for:
<Details PCPCarrier="DoctorsName">
This is not a node called Details PCPCarrier; it is a node called Details with an attribute called PCPCarrier.
So the XPath to select it would be:
/Root/Report/Tablix2/Detail_Collections/Details
Or, if you want to specifically filter by the PCPCarrier attribute existing:
/Root/Report/Tablix2/Detail_Collections/Details[#PCPCarrier]
Or, to get the value of the attribute itself:
/Root/Report/Tablix2/Detail_Collections/Details/#PCPCarrier
IMSoP pointed me in the right direction and I figured out the rest myself.
I also needed to add this:
With XMLNAMESPACES (Default 'AdmissionsByPCP')
So the query looks like this:
Declare #XMLData as XML
Set #XMLData=(
Select *
FROM OPENROWSET (Bulk '\\Directory\AdmissionsByPCP.xml',
Single_Clob) a );
With XMLNAMESPACES (Default 'AdmissionsByPCP')
Select
#XMLData.value('(/Report/Tablix2/Details_Collection/Details/#PCPCarrier)
[1]', 'varchar(max)')

Combine and modify XML in TSQL

Using SQL Server 2005, is it possible to combine XML and add an attribute at same time?
Unfortunately, due to project restrictions, I need a SQL Server 2005 solution.
Consider the following, where I need to combine XML from multiple rows within a new <root> element...
; WITH [TestTable] AS (
SELECT 7 AS [PkId], CAST('<data><id>11</id><id>12</id></data>' AS XML) AS [Data]
UNION ALL
SELECT 12, CAST('<data><id>22</id></data>' AS XML)
UNION ALL
SELECT 43, CAST('<data><id>33</id></data>' AS XML)
)
SELECT (
SELECT XMLDATA as [*]
FROM (
SELECT [Data] AS [*]
FROM [TestTable]
FOR XML PATH(''), TYPE
) AS DATA(XMLDATA)
FOR XML PATH('root')
)
This produces the desired output of...
<root>
<data><id>11</id><id>12</id></data>
<data><id>22</id></data>
<data><id>33</id></data>
</root>
But what I need to do, if possible, is add an attribute to the existing data element in each of the rows with the PkId value. The desired output would then look like this...
<root>
<data pkid="7"><id>11</id><id>12</id></data>
<data pkid="12"><id>22</id></data>
<data pkid="43"><id>33</id></data>
</root>
My gut feeling is that this is going to be impossible without the use of a cursor, but if anybody knows a way of doing it I'd love to hear it.
At the request of #MattA, here is an example of some random data in the table...
[PkId] [UserId] [SubmittedDate] [Data]
1 1 2015-03-24 12:34:56 '<data><id>1</id><id>2</id></data>'
2 1 2015-03-23 09:15:52 '<data><id>3</id></data>'
3 2 2015-03-22 16:01:23 '<data><id>4</id><id>5</id></data>'
4 1 2015-03-21 13:45:34 '<data><id>6</id></data>'
Please note, that to make the question easier, I stated that I needed the PkId column as the attribute to the data. This is not actually the case - instead I need the [SubmittedDate] column to be used. I apologise if this caused confusion.
Using UserId=1 as a filter, the XML I would like from the above would be...
<root>
<data submitteddate="2015-03-24T12:34:56"><id>1</id><id>2</id></data>
<data submitteddate="2015-03-23T09:15:52"><id>3</id></data>
<data submitteddate="2015-03-21T13:45:34"><id>6</id></data>
</root>
The date would be formatted using the 126 date format available from CONVERT
Here's the quick answer for you. XML does support "modify", but shredding on a small data set like this works quite well too.
Code
--The existing XML
DECLARE #XML XML = '<root>
<data><id>11</id></data>
<data><id>22</id></data>
<data><id>33</id></data>
</root>'
--XML Shredded Back to a table
;WITH
ShreddedXML AS (
SELECT
ID = FieldAlias.value('(id)[1]','int')
FROM
#XML.nodes('/root/data') AS TableAlias(FieldAlias)
), ArbitraryPKGenerator AS (
SELECT CURRENT_TIMESTAMP AS PKid,
ID
FROM ShreddedXML
)
SELECT A.PKId AS "#PKid",
A.ID AS "id"
FROM ArbitraryPKGenerator AS A
FOR XML PATH('data'), ROOT('root')
And the XML
<root>
<data PKid="2015-03-24T09:44:55.770">
<id>11</id>
</data>
<data PKid="2015-03-24T09:44:55.770">
<id>22</id>
</data>
<data PKid="2015-03-24T09:44:55.770">
<id>33</id>
</data>
</root>

Get followin sibling in SQL Server XPath

Since SQL Server does not support following-sibling axis - what is the best way to get it? Let's say I have XML like this and I would like to get the first 'b' node after a node matching the value 'dog':
<root>
<a>cat</a>
<b>Cats don't like milk</b>
<a>dog</a>
<b>Dogs like everything</b>
</root>
You could try something like this.
declare #X xml = '
<root>
<a>cat</a>
<b>Cats don''t like milk</b>
<a>dog</a>
<c>not this</c>
<b>Dogs like everything</b>
<b>and not this</b>
</root>'
select #X.query('(/root/b[. >> (/root/a[. = "dog"])[1]])[1]')

SQL - Read an XML node from a table field

I am using SQL Server 2008. I have a field called RequestParameters in one of my SQL table called Requests with XML data. An example would be:
<RequestParameters xmlns="http://schemas.datacontract.org/2004/07/My.Name.Space" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="1">
<Data z:Id="2" i:type="CheckoutRequest">
<UserGuid>7ec38c44-5aa6-49e6-9fc7-25e9028f2148</UserGuid>
<DefaultData i:nil="true" />
</Data>
</RequestParameters>
I ultimately want to retrieve the value of UserGuid. For that, I am doing this:
SELECT RequestParameters.value('(/RequestParameters/Data/UserGuid)[0]', 'uniqueidentifier') as UserGuid
FROM Requests
However, the results I am seeing are all NULL. What am I doing wrong?
You have to specify the default namespace and use [1] instead of [0].
WITH XMLNAMESPACES(default 'http://schemas.datacontract.org/2004/07/My.Name.Space')
SELECT RequestParameters.value('(/RequestParameters/Data/UserGuid)[1]', 'uniqueidentifier') as UserGuid
FROM Requests;
SQL Fiddle
declare #XML xml
set #XML = "<RequestParameters xmlns="http://schemas.datacontract.org/2004/07/My.Name.Space" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="1">
<Data z:Id="2" i:type="CheckoutRequest">
<UserGuid>7ec38c44-5aa6-49e6-9fc7-25e9028f2148</UserGuid>
<DefaultData i:nil="true" />
</Data>
</RequestParameters>"
select #XML.value('(/RequestParameters/Data /UserGuid)[1]', 'varchar')
'

Resources