I have a table where one field called 'configuration' is type of XML:
<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>
What I would like to do, is to retrieve all the table records or at least count the table records that have a field 'configuration' containing at least one 'element' attribute containing a 'value' attribute equals to 'lisa'.
What I have for the moment, is a query that can retrieve the 'value' attribute of the specified 'element' position, for example:
select Configuration.value('(/configuration/element/#value)[0]', 'nvarchar(max)') // returns me 'john'
select Configuration.value('(/configuration/element/#value)[1]', 'nvarchar(max)') // returns me 'kevin'
This is a bit of pseudo-SQL in the absence of a dataset, and a bit of guesswork; in that I (think) you simply want to return the rows(?) where there is a the node configuration/element has the value property 'lisa'. IF my guess is right, then something like this will work (you'll ened to replace object names in Braces({}):
SELECT {Columns}
FROM [{Your Table}] YT
WHERE EXISTS (SELECT 1
FROM [{Your Table}] E
CROSS APPLY E.[{Your XML Column}].nodes('configuration/element') C(E)
WHERE E.[{Your ID Column}] = YT.[{Your ID Column}]
AND C.E.value('./#value','varchar(50)') = 'lisa');
Example:
WITH VTE AS(
SELECT 1 AS ID,
CONVERT(xml,'<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>') AS XMlCol
UNION ALL
SELECT 2 AS ID,
CONVERT(xml,'<configuration>
<element value="craig" />
<element value="donald" />
<element value="jenny" />
<element value="jayne" />
</configuration>') AS XMlCol)
SELECT *
FROM VTE YT
WHERE EXISTS (SELECT 1
FROM VTE E
CROSS APPLY E.XMlCol.nodes('configuration/element') C(E)
WHERE E.ID = YT.ID
AND C.E.value('./#value','varchar(50)') = 'lisa');
This only returns the row with an ID of 1.
Please try the below,
declare #xml as xml
set #xml='<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>'
SELECT T.c.value('./#value','nvarchar(250)' ) As element
FROM #xml.nodes('//element') AS T(c)
Related
Started doing some SQL/XML resently but i have the problem of doing count functions.
Lets say i have the database
<Root>
<Element ATTTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="C" ATTRIBUTE2="4" />
<Element ATTRIBUTE1 ="C" ATTRIBUTE2="4" />
</Root>
What can i write in SLQ/XML to make it count how many of each i have that have the two same attributes? So for example i have 5 elements of with attributes A and 1, 2 attributes of A and 3 and two attributes of B and 3 and so on.
I have tried to group them but i kind of just split them up outside the root then.
Within SQL Server I'm trying to select values from what I think is a XSD string.
e.g. Given the following SQL Server table
CREATE TABLE dbo.TextXML (
ID INT PRIMARY KEY,
Data NVARCHAR(max))
INSERT INTO dbo.TextXML ( ID, Data )
SELECT 1,
('<element name="Rownum" value="Row23" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="1234" />
</element>
<element name="ENABLESSL" value="false" />' )
INSERT INTO dbo.TextXML ( ID, Data )
SELECT 2,
('<element name="Rownum" value="Row24" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="5678" />
</element>
<element name="ENABLESSL" value="true" />' );
I want to be able to select the values for given element names. Something like ...
SELECT ID, Data.CONNECTIONTYPESECTION, Data.EchoData.0007, Data.EchoData.MessageType, Data.ENABLESSL
FROM TextXML
WHERE Data.Rownum = "Row23" AND Data.EchoData.MessageType = "1234".
ID Data.CONNECTIONTYPESECTION Data.EchoData.0007 Data.EchoData.MessageType Data.ENABLESSL
1 True 0805193143 1234 true
I can use CHARINDEX and SUBSTRING but have to hardcode the length of the "name" value and this asumes the "value" is always the same length. I'm hoping there is a better and more efficient way do do this.
I have experimented with CROSS APPPLY and XML VALUE functions but this only returns the first element in the Data field. I also could not find out how to search for a particular element "name" to get its value
Please try the following T-SQL.
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, Data NVARCHAR(max));
INSERT INTO #tbl (Data) VALUES
(N'<element name="Rownum" value="Row23"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="1234"/>
</element>
<element name="ENABLESSL" value="false"/>'),
(N'<element name="Rownum" value="Row24"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="5678"/>
</element>
<element name="ENABLESSL" value="true"/>');
-- DDL and sample data population, end
;WITH rs AS
(
SELECT *
, TRY_CAST(data AS XML) AS xmldata
FROM #tbl
)
SELECT rs.ID
, xmldata.value('(element[#name="CONNECTIONTYPESECTION"]/#value)[1]','VARCHAR(10)') AS CONNECTIONTYPESECTION
, xmldata.value('(element[#name="EchoData"]/element[#name="0007"]/#value)[1]','VARCHAR(10)') AS [EchoData.0007]
, xmldata.value('(element[#name="EchoData"]/element[#name="MessageType"]/#value)[1]','VARCHAR(10)') AS [EchoData.MessageType]
, xmldata.value('(element[#name="ENABLESSL"]/#value)[1]','VARCHAR(10)') AS [Data.ENABLESSL]
FROM rs
WHERE xmldata.value('(element[#name="Rownum"]/#value)[1]','VARCHAR(30)') = 'Row23'
AND xmldata.value('(element[#name="EchoData"]/element[#name="MessageType"]/#value)[1]','VARCHAR(10)') = '1234';
Output
+----+-----------------------+---------------+----------------------+----------------+
| ID | CONNECTIONTYPESECTION | EchoData.0007 | EchoData.MessageType | Data.ENABLESSL |
+----+-----------------------+---------------+----------------------+----------------+
| 1 | True | 0805193143 | 1234 | false |
+----+-----------------------+---------------+----------------------+----------------+
One of my tables with xml datatype has the following xml information:
<RequestMetaData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MetaData Type="DocImport">
<Keywords>
<Key Name="Zone" Value="MIO" />
<Key Name="ClassificationStrategy" Value="NeedClassification" />
<Key Name="Folder" Value="0456e6ca" />
</Keywords>
</MetaData>
<MetaData Type="SourceResponse">
<Keywords>
<Key Name="NotificationResponse_20180427-150426" Value="Received successful response from Source" />
</Keywords>
</MetaData>
</RequestMetaData>
I need to write an SQL query to fetch the value of Classification strategy based on key name.
I have added the xml in a variable #xml and used the following code. It is returning NULL.
select A.b.value('ClassificationStrategy[1]', 'VARCHAR(30)') AS CS
FROM #xml.nodes('/RequestMetaData/MetaData/Keywords') AS A(b)
Can someone please help me with this.
You can read your XML in various ways. Use a simple .value() with an XPath/XQuery expression to retrieve a single value, use .query to retrieve a part of the XML or use .nodes() to return repeated elements as derived table:
DECLARE #xml XML=
N'<RequestMetaData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MetaData Type="DocImport">
<Keywords>
<Key Name="Zone" Value="MIO" />
<Key Name="ClassificationStrategy" Value="NeedClassification" />
<Key Name="Folder" Value="0456e6ca" />
</Keywords>
</MetaData>
<MetaData Type="SourceResponse">
<Keywords>
<Key Name="NotificationResponse_20180427-150426" Value="Received successful response from Source" />
</Keywords>
</MetaData>
</RequestMetaData>';
--Read the whole lot
SELECT md.value('#Type','nvarchar(max)') AS MetaDataType
,k.value('#Name','nvarchar(max)') AS KeyName
,k.value('#Value','nvarchar(max)') AS KeyValue
FROM #xml.nodes('/RequestMetaData/MetaData') A(md)
OUTER APPLY md.nodes('Keywords/Key') B(k);
--Get one key's value by name (anywhere in the doc)
DECLARE #keyName VARCHAR(100)='ClassificationStrategy';
SELECT #xml.value('(//Key[#Name=sql:variable("#keyName")]/#Value)[1]','nvarchar(max)');
--Use the meta data type as additional filter (if key names are not unique per doc)
DECLARE #kName VARCHAR(100)='ClassificationStrategy';
DECLARE #mdType VARCHAR(100)='DocImport';
SELECT #xml.value('(/RequestMetaData
/MetaData[#Type=sql:variable("#mdType")]
/Keywords
/Key[#Name=sql:variable("#kName")]
/#Value)[1]','nvarchar(max)');
i am new to xml queries. i have one xml like
<fields>
<fields name = "a" active ="1" mandat ="true"/>
<fields name = "a" active ="1"/>
</fields>
Now i need to find all the field names that manadt is true. How can i query xml using sql server. please help
Your question is not quite clear, especially the tags (sql, xml, c#-4.0), but from you question's text I take, that you need to query the XML's content within SQL-Server.
You can try it like this
DECLARE #xml XML=
N'<fields>
<fields name="a" active="1" mandat="true" />
<fields name="a" active="1" />
</fields>';
SELECT fld.value(N'#name',N'nvarchar(max)') AS Field_Name
,fld.value(N'#active',N'bit') AS Field_Active
,fld.value(N'#mandat',N'bit') AS Field_Mandant
FROM #xml.nodes(N'/fields/fields') AS A(fld)
The result
Field_Name Field_Active Field_Mandant
a 1 1
a 1 NULL
UPDATE
If you want to read the value of #name of the fields-node, where #mandat is "true", do it like this:
DECLARE #xml XML=
N'<fields>
<fields name="a" active="1" mandat="true" />
<fields name="a" active="1" />
</fields>';
SELECT #xml.value(N'(/fields/fields[#mandat="true"]/#name)[1]',N'nvarchar(max)') AS Mandant_Name
UPDATE 2: More than one <fields> with #mandat="true"
Just try my first solution with a predicate in .nodes():
DECLARE #xml XML=
N'<fields>
<fields name="a" active="1" mandat="true" />
<fields name="b" active="2" />
<fields name="c" active="3" mandat="false" />
<fields name="d" active="4" mandat="true" />
</fields>';
SELECT fld.value(N'#name',N'nvarchar(max)') AS Field_Name
,fld.value(N'#active',N'bit') AS Field_Active
,fld.value(N'#mandat',N'bit') AS Field_Mandant
FROM #xml.nodes(N'/fields/fields[#mandat="true"]') AS A(fld)
This will return only the first and the last <fields> node
I have the XML below in a column. I need to get to \Report\Criterias\Criteria (where name="Advertisers")\Elements\Element(where name="ListViewAvailable"). From here I need to list all the numbers that are in the Value element.
So far I got:
SELECT xmlColumn.query('/Report/Criterias/Criteria/Elements/Element')
from tbl
but no idea how to filter.
<Report>
<Criterias>
<Criteria name="Date Range">
...
</Criteria>
<Criteria name="Advertisers">
<Elements>
<Element name="CheckBoxOne">
<Value>0</Value>
</Element>
<Element name="ListViewAvailable">
<Value>314</Value>
<Value>57</Value>
<Value>18886</Value>
<Value>7437</Value>
</Element>
</Elements>
</Criteria>
<Criteria name="Revenue Types">
...
</Criteria>
</Criterias>
</Report>
You can filter using predicate ([]) in combination with CROSS APPLY to shred the XML on Value elements level :
SELECT C.value('.', 'int') AS Value
FROM tbl t
CROSS APPLY t.xmlColumn.nodes('
/Report/Criterias/Criteria[#name="Advertisers"]
/Elements/Element[#name="ListViewAvailable"]
/Value
') T(C)