How to find xml node id using SQL Server 2012? - sql

I have a column called content in application table that contains XML like this:
<?xml version="1.0" ?>
<XmlData>
<dataitem id="Hello" value="true" />
</XmlData>
This value in one row same like another row and so on
My problem is that now I want to find which rows have an id attribute with the value of Hello.
How can I do this?
Please help me.
Thanks in Advance

You need to study xml Data Type Methods if you want to process XML data with SQL Server. Find below one of possible solutions:
-- Here is your data
declare #YourTable table (
YourXmlField XML
)
insert into #YourTable values (
'<?xml version="1.0" ?>
<XmlData>
<dataitem id="Hello" value="true" />
</XmlData>'
)
-- Here is solution
select x.xmldata.value('(#value)[1]', 'varchar(10)')
from #YourTable t
cross apply t.YourXmlField.nodes('/XmlData/dataitem') x(xmldata)

Related

Extract all the XML entry key values as rows using SQL

I'm trying to extract the key values (1,2,3) from a single row in a table, but I'm only able to extract a single row at a time using what I know:
cast([attributes] as XML).value('(//Map/entry[#key="catalogItem"]/value/Map/entry/#key)[1]','VARCHAR(20)')
Depending on what number I put in the [x] I get that entry.
I tried removing the [x] and got the error: XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
<Map>
<entry key="catalogItem">
<value>
<Map>
<entry key="1" value="x"/>
<entry key="2" value="y"/>
<entry key="3" value="z"/>
I want the results to be a single column
1
2
3
Please try the following solution.
A combination of XQuery methods .nodes() and .value() gives what you need.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (id INT IDENTITY PRIMARY KEY, XMLColumn XML);
INSERT INTO #tbl (XMLColumn) VALUES
(N'<Map>
<entry key="catalogItem">
<value>
<Map>
<entry key="1" value="x"/>
<entry key="2" value="y"/>
<entry key="3" value="z"/>
</Map>
</value>
</entry>
</Map>');
-- DDL and sample data population, end
SELECT t.*
, c.value('#key', 'INT') AS [key]
FROM #tbl AS t
CROSS APPLY XMLColumn.nodes('/Map/entry/value/Map/entry') AS t1(c);
Output
id
key
1
1
1
2
1
3

SQL Server XML data type combine multiple rows

I have a SQL Server 2014 table containing hundreds of XML rows. All the xml objects have the same structure.
create table table1
(
createdOn datetime,
row xml
)
How can I query multiple rows (about 20 files show up daily and they must be stored as received)?
Row 1
<Products>
<product>
<productID>1</productID>
<product>Bilberry</product>
<price>10</price>
</product>
<product>
<productID>2</productID>
<product>Lychee</product>
<price>5</price>
</product>
</Products>
Row 2
<Products>
<product>
<productID>3</productID>
<product>Mango</product>
</product>
<product>
<productID>4</productID>
<product>Blackcurrant</product>
</product>
</Products>
Thanks
Apologies for deleting the answer provided
It worked perfectly
SELECT
ID
,Tab.Col.value('productID[1]', 'int') as ProductID
FROM [dbo].table1 a
CROSS APPLY a.XMLData.nodes('/Products/product') Tab(Col)
Thanks

Search for a particular column name from with a XML column in SQL Server

Just wanted to get some help here. I have a situation where I need to find some data from within the <Column Name> tag as shown in the XML below.
I had a issue where some badly formatted data was exported in the system, I found that piece but now there is a process where I IMPORT data out of the system. Now I have a table which contains XML stored.
I have to iterate through the whole table to see if that column name exists in that particular ID column and if it does I will return the ID. Say for example my table name is Sample and the columns are (ID, ImportXML).
Any help on how I can achieve this ? New to dealing with XML from within SQL Server.
<?xml version="1.0" encoding="UTF-8"?>
<ExportConfiguration id="SampleExport">
<definitions>
<ClientName Value="Sample"/>
<FileType Value="XML"/>
<FileName>
<Value Value="SomeValue"/>
</FileName>
<Columns>
<Column Name="abc" DataType="String" Value="test123"/>
<Column Name="findthis" DataType="String" Value="Test456"/>
</Columns>
</definitions>
</ExportConfiguration>
So basically from the above mentioned code I want to get the value from within <Columns>/<Column Name> = "findthis" so basically findthis is my keyword and I want to get all the ID's of the columns which contain the keyword findthis just for argument sake.
Something like this:
-- Test table.
declare #xTable table (ID int identity(1,1) primary key clustered, XMLData xml)
-- Insert an XML document. I only did one, but the same would work for multiple
insert into #xTable
select '<?xml version="1.0" encoding="UTF-8"?>
<ExportConfiguration id="SampleExport">
<definitions>
<ClientName Value="Sample"/>
<FileType Value="XML"/>
<FileName>
<Value Value="SomeValue"/>
</FileName>
<Columns>
<Column Name="abc" DataType="String" Value="test123"/>
<Column Name="findthis" DataType="String" Value="Test456"/>
</Columns>
</definitions>
</ExportConfiguration>'
-- Return everything from the table with your XML where there is an attribute at the path "/ExportConfiguration/definitions/Columns/Column" with the name "Name" and the value "findthis"
select *
from #xTable
where XMLData.exist('/ExportConfiguration/definitions/Columns/Column[#Name eq "findthis"]') = 1

Querying XML field in database table using SQL

I have a table named VehicleHistoryBlob that has the following structure:
VehicleHistoryBlobId int PRIMARY KEY
VehicleHistoryBlob XML
I need to write SQL that finds all entries in VehicleHistoryBlob XML that have Bus as a parent node and Destination as a child node (Bus can have many Destinations, and the parent node in the XML is not always a Bus).
<Bus>
...
<Destination>
<Name>The big building</Name>
<DestinationCode> A21301423 </DestinationCode>
<DestinationAddress> 440 Mountain View Parade </DestinationAddress>
<DestinationCountry> USA </DestinationCountry>
</Destination>
</Bus>'
I need to query through the XML and find all entries that have Bus as a parent node and Destination as a child node, and pass the VehicleHistoryBlobId associated with the XML into my temporary table #tmpTable
DECLARE #tmpTable TABLE(theints INT)
I have been trying to manipulate the .nodes function but I am struggling to yield accurate results due to my lack of experience with XML as a data type.
Thanks in advance!
To filter row by certain condition on the XML column, you can use exist() method instead of nodes(). For example, the following query insert to #temptable VehicleHistoryBlobId where corresponding XML has Bus as root element and Destination child element :
INSERT INTO #tmpTable
SELECT v.VehicleHistoryBlobId
FROM VehicleHistoryBlob v
WHERE v.VehicleHistoryBlob.exist('/Bus/Destination') = 1
sqlfiddle demo

How to use openXML() for Complex XMLs in SQL Server 2005

I have the following complex XML
<Collection>
<VOUCHER>
<DATE TYPE="Date">20110401</DATE>
<NARRATION TYPE="String">MUNNA CONVENT ROAD</NARRATION>
<VOUCHERTYPENAME>RETAIL</VOUCHERTYPENAME>
<VOUCHERNUMBER>R-2-I2-9-6-27751</VOUCHERNUMBER>
<ALLLEDGERENTRIES.LIST>
<LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
<AMOUNT>-2678.9985</AMOUNT>
</ALLLEDGERENTRIES.LIST>
<ALLLEDGERENTRIES.LIST>
<LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
<AMOUNT>-2678.9985</AMOUNT>
</ALLLEDGERENTRIES.LIST>
</VOUCHER>
<VOUCHER>
<DATE TYPE="Date">20110401</DATE>
<NARRATION TYPE="String">MUNNA CONVENT ROAD</NARRATION>
<VOUCHERTYPENAME>RETAIL</VOUCHERTYPENAME>
<VOUCHERNUMBER>R-2-I2-9-6-27751</VOUCHERNUMBER>
<ALLLEDGERENTRIES.LIST>
<LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
<AMOUNT>-2678.9985</AMOUNT>
</ALLLEDGERENTRIES.LIST>
<ALLLEDGERENTRIES.LIST>
<LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
<AMOUNT>-2678.9985</AMOUNT>
</ALLLEDGERENTRIES.LIST>
</VOUCHER>
</Collection>
I'm saving voucher details in 1 table, ALLLEDGERENTRIES.LIST details in another table.
Both tables have relation on VoucherID. For a particular VoucherID the related x3 values should be stored. In my stored procedure I'm using openxml().
Piece of my SP:
INSERT INTO SalesVoucher(AbsID,VoucherNumber,VoucherTypeName,Narration,VoucherDate)
SELECT #AID,VOUCHERNUMBER,VOUCHERTYPENAME,NARRATION,CAST(DATE AS DATETIME)
FROM OPENXML(#XMLHandle,'ENVELOPE/BODY/DATA/COLLECTION/VOUCHER',3)
WITH (
VOUCHERNUMBER nVarchar(200),VOUCHERTYPENAME varchar(100),NARRATION varchar(500),DATE DATETIME
)
SELECT #VID=##IDENTITY
INSERT INTO SalesLedger(VoucherID,LedgerName,Amount)
SELECT #VID,LEDGERNAME,AMOUNT
FROM OPENXML(#XMLHandle,'ENVELOPE/BODY/DATA/COLLECTION/VOUCHER/ALLLEDGERENTRIES.LIST',3)
WITH(
LEDGERNAME varchar(200),AMOUNT decimal(18,0)
)
All values are storing in DB but the column VoucherID in SalesLedger table is same for all the rows (it should not..) as I used ##IDENTITY it is returning last identity value only.
Please someone help me how to store related voucherID in SalesLedger table using openxml() in sql...
I would probably use the native XQuery capabilities of SQL Server to do this. First, grab the items you need for your SalesVoucher table and insert those.
When you come to insert the details, your "parent" info is already stored in the SalesVoucher table - so go grab the necessary info from there.
Your code would be something like this (assuming your XML data is in a SQL variable called #input of type XML):
-- Insert the "parent" info into SalesVoucher
INSERT INTO dbo.SalesVoucher(VoucherNumber, VoucherTypeName, Narration, VoucherDate)
SELECT
v.value('(VOUCHERNUMBER)[1]', 'NVARCHAR(200)'),
v.value('(VOUCHERTYPENAME)[1]', 'VARCHAR(100)'),
v.value('(NARRATION)[1]', 'VARCHAR(500)'),
v.value('(DATE)[1]', 'DATETIME')
FROM
#input.nodes('/Collection/VOUCHER') AS Coll(V)
This inserts the basic info in your SalesVoucher table.
When you want to parse the details, you need to make a reference back to the VoucherNumber of the parent - with that info, you can retrieve the AbsID from SalesVoucher and insert the appropriate value into SalesLedger:
INSERT INTO #SalesLedger (VoucherID, LedgerName, Amount)
SELECT
sv.AbsID,
AL.LS.value('(LEDGERNAME)[1]', 'VARCHAR(200)'),
AL.LS.value('(AMOUNT)[1]', 'DECIMAL(18,4)')
FROM
#input.nodes('/Collection/VOUCHER') AS Coll(V)
INNER JOIN
dbo.SalesVoucher sv
ON sv.VoucherNumber = v.value('(VOUCHERNUMBER)[1]', 'NVARCHAR(200)')
CROSS APPLY
Coll.V.nodes('.//ALLLEDGERENTRIES.LIST') AS AL(LS)
The CROSS APPLY gets the details for that one particular node, and thus "connects" the details to the "parent" info for the VoucherNumber in the XML above.
As as PS: a datatype of DECIMAL(18,0) is not suitable for values like -2678.9985. DECIMAL(18,0) will store a maximum of 18 digits, but 0 of which after the decimal point - so this value would be stored as -2679. I've changed this to a more useful datatype of DECIMAL(18,4) - 18 digits max, 4 of which after the decimal point.