I have an xml variable.
DECLARE #xml xml = N'<Items Category="AAA">
<Item Id="1">A</Item>
<Item Id="2">B</Item>
<Item Id="3">C</Item>
<Item Id="4">D</Item>
<Item Id="5">E</Item>
<Item Id="6">F</Item>
<Item Id="7">G</Item>
<Item Id="8">H</Item>
<Item Id="9">I</Item>
</Items>'
Could you help me write a query to split it into several pieces?
<Items Category="AAA">
<Item Id="1">A</Item>
<Item Id="2">B</Item>
<Item Id="3">C</Item>
</Items>
<Items Category="AAA">
<Item Id="4">D</Item>
<Item Id="5">E</Item>
<Item Id="6">F</Item>
</Items>
<Items Category="AAA">
<Item Id="7">G</Item>
<Item Id="8">H</Item>
<Item Id="9">I</Item>
</Items>
I mean XQuery, but any other idea is welcome.
Way to do this via XQuery modify:
DECLARE #xml xml = N'<Items Category="AAA">
<Item Id="1">A</Item>
<Item Id="2">B</Item>
<Item Id="3">C</Item>
<Item Id="4">D</Item>
<Item Id="5">E</Item>
<Item Id="6">F</Item>
<Item Id="7">G</Item>
<Item Id="8">H</Item>
<Item Id="9">I</Item>
</Items>';
DECLARE #temp TABLE (XmlData1 xml, XmlData2 xml, XmlData3 xml);
INSERT #temp VALUES (#xml, #xml, #xml);
UPDATE t
SET XmlData1.modify('delete /Items/Item[not(position() >= 1 and position() < 4)]'),
XmlData2.modify('delete /Items/Item[not(position() >= 4 and position() < 7)]'),
XmlData3.modify('delete /Items/Item[not(position() >= 7 and position() < 10)]')
FROM #temp t;
SELECT * FROM #temp;
Way to do this via FLWOR:
select #xml.query('
<Items Category="AAA">
{
for $item in /Items/Item[position() >= 1 and position() < 4]
return $item
}
</Items>');
You can freely change your split criteria in XPath.
Related
I started working for the first time and I don't know much yet, I've been suffering with this problem for two days.
I have a document of this type:
<Tables>
<dbo.ES_Connection_Modes>
<Item />
</dbo.ES_Connection_Modes>
<dbo.ES_Device_Categories>
<Item>
<LINK>1</LINK>
<F_Class>1</F_Class>
<N_Code>1</N_Code>
<B_Default>1</B_Default>
<B_Meter>1</B_Meter>
<B_Tranf>0</B_Tranf>
<B_Regist>0</B_Regist>
<B_Show_InMenu>1</B_Show_InMenu>
<N_Project>-1</N_Project>
<C_Const>EDC_Meter</C_Const>
</Item>
</dbo.ES_Device_Categories>
<dbo.ES_Indicating_Device_Types>
<Item />
</dbo.ES_Indicating_Device_Types>
<dbo.ES_Operating_Principles>
<Item />
</dbo.ES_Operating_Principles>
<dbo.ES_Precission_Classes>
<Item>
<LINK>7</LINK>
<N_Project>687783</N_Project>
<C_Name>2,0</C_Name>
<C_Const>EPC_20</C_Const>
</Item>
<Item>
<LINK>8</LINK>
<N_Project>687783</N_Project>
<C_Name>2,5</C_Name>
<C_Const>EPC_25</C_Const>
</Item>
</dbo.ES_Precission_Classes>
<dbo.ES_Granularity>
<Item />
</dbo.ES_Granularity>
</Tables>
I need to delete the empty item containers and the container containing it to get a document of the following type:
<Tables>
<dbo.ES_Device_Categories>
<Item>
<LINK>1</LINK>
<F_Class>1</F_Class>
<N_Code>1</N_Code>
<B_Default>1</B_Default>
<B_Meter>1</B_Meter>
<B_Tranf>0</B_Tranf>
<B_Regist>0</B_Regist>
<B_Show_InMenu>1</B_Show_InMenu>
<N_Project>-1</N_Project>
<C_Const>EDC_Meter</C_Const>
</Item>
</dbo.ES_Device_Categories>
<dbo.ES_Precission_Classes>
<Item>
<LINK>7</LINK>
<N_Project>687783</N_Project>
<C_Name>2,0</C_Name>
<C_Const>EPC_20</C_Const>
</Item>
<Item>
<LINK>8</LINK>
<N_Project>687783</N_Project>
<C_Name>2,5</C_Name>
<C_Const>EPC_25</C_Const>
</Item>
</dbo.ES_Precission_Classes>
</Tables>
I've tried a lot of things, deleted them, but here's the way I was hoping for, but I get an error:
SET #myDoc.modify('delete /Tables/*[contains(name(), "null")]');
Please try the following solution.
It is deleting 2nd level XML elements under the root (Tables) that have in turn Item elements without children.
SQL
DECLARE #myDoc XML =
N'<Tables>
<dbo.ES_Connection_Modes>
<Item/>
</dbo.ES_Connection_Modes>
<dbo.ES_Device_Categories>
<Item>
<LINK>1</LINK>
<F_Class>1</F_Class>
<N_Code>1</N_Code>
<B_Default>1</B_Default>
<B_Meter>1</B_Meter>
<B_Tranf>0</B_Tranf>
<B_Regist>0</B_Regist>
<B_Show_InMenu>1</B_Show_InMenu>
<N_Project>-1</N_Project>
<C_Const>EDC_Meter</C_Const>
</Item>
</dbo.ES_Device_Categories>
<dbo.ES_Indicating_Device_Types>
<Item/>
</dbo.ES_Indicating_Device_Types>
<dbo.ES_Operating_Principles>
<Item/>
</dbo.ES_Operating_Principles>
<dbo.ES_Precission_Classes>
<Item>
<LINK>7</LINK>
<N_Project>687783</N_Project>
<C_Name>2,0</C_Name>
<C_Const>EPC_20</C_Const>
</Item>
<Item>
<LINK>8</LINK>
<N_Project>687783</N_Project>
<C_Name>2,5</C_Name>
<C_Const>EPC_25</C_Const>
</Item>
</dbo.ES_Precission_Classes>
<dbo.ES_Granularity>
<Item/>
</dbo.ES_Granularity>
</Tables>';
SET #myDoc.modify('delete /Tables/*[not(Item/*)]');
-- test
SELECT #myDoc;
I have an XML file that looks like this:
<NodeA Type="A" Date="2015-10-28">
<NodeB Amount="0.00">
<Items />
</NodeB>
<NodeB Amount="0.00">
<Items>
<Item code="2" val="50.00" />
<Item code="8" val="50.00" />
</Items>
</NodeB>
</NodeA>
I am trying to use SQL Server and XPath to extract the child nodes of NodeA as XML.
Based on the above XML, I need to return a table with 2 rows, containing the following fields:
Type (nvarchar) | Date (Date) | ChildNode (XML)
-----------------------------------------------
A 2015-10-28 <NodeB Amount="0.00"><Items /></NodeB>
A 2015-10-28 <NodeB Amount="0.00"><Items>...</NodeB>
I know I can do this using C#, but is there a way to do this using XPath? I've some success with xPath returning the field values from NodeA, but can't seem to get NodeB to display as XML.
Try this -
DECLARE #xml AS XML
SET #xml = '<NodeA Type="A" Date="2015-10-28">
<NodeB Amount="0.00">
<Items />
</NodeB>
<NodeB Amount="0.00">
<Items>
<Item code="2" val="50.00" />
<Item code="8" val="50.00" />
</Items>
</NodeB>
</NodeA>'
SELECT c.value('(/NodeA/#Type)[1]', 'varchar(50)') AS Type,
c.value('(/NodeA/#Date)[1]', 'varchar(50)') AS Date,
c.query('.') AS ChildNodeXML
FROM #xml.nodes('/NodeA/NodeB') as T(C)
Result
Type Date ChildNodeXML
---- ------ ----------------------------------
A 2015-10-28 <NodeB Amount="0.00"><Items /></NodeB>
A 2015-10-28 <NodeB Amount="0.00"><Items><Item code="2" val="50.00" /><Item code="8" val="50.00" /></Items></NodeB>
I tried to print the details of 3rd and 4th products in the catalog, but I am getting empty results.
XML input:
<catalog>
<product dept="WMN">
<number>557</number>
<name language="en">Fleece Pullover</name>
<colorChoices>navy black</colorChoices>
</product>
<product dept="ACC">
<number>563</number>
<name language="en">Floppy Sun Hat</name>
</product>
<product dept="ACC">
<number>443</number>
<name language="en">Deluxe Travel Bag</name>
</product>
<product dept="MEN">
<number>784</number>
<name language="en">Cotton Dress Shirt</name>
<colorChoices>white gray</colorChoices>
<desc>Our <i>favorite</i> shirt!</desc>
</product>
</catalog>
what I tried:
SELECT xDoc.query(' for $prod in //product
let $x:=$prod
return (<Item>{data($x[3])}{data($x[4])}</Item>)')
FROM AdminDocs
where id=6
Output displayed:
<Item />
<Item />
<Item />
<Item />
This defines a loop over all products:
for $prod in //product
For each of those products, you return the third and fourth node out of a sequence of a single product, which obviously will yield empty nodes:
let $x:=$prod
return (<Item>{data($x[3])}{data($x[4])}</Item>)
For a better understanding, return the whole product node each time:
for $prod in //product
return <item>{ $prod }</item>
Which will result in something like this:
<item>
<product dept="WMN">
<number>557</number>
<name language="en">Fleece Pullover</name>
<colorChoices>navy black</colorChoices>
</product>
</item>
<item>
<product dept="ACC">
<number>563</number>
<name language="en">Floppy Sun Hat</name>
</product>
</item>
<item>
<product dept="ACC">
<number>443</number>
<name language="en">Deluxe Travel Bag</name>
</product>
</item>
<item>
<product dept="MEN">
<number>784</number>
<name language="en">Cotton Dress Shirt</name>
<colorChoices>white gray</colorChoices>
<desc>Our <i>favorite</i> shirt!</desc>
</product>
</item>
And each of those <product/> elements being a $prod[1]. Try:
for $prod in //product
return <item>{ $prod[1] }</item>
which will return the exactly same result, compared to
for $prod in //product
return <item>{ $prod[2] }</item>
(or any other positional predicate) resulting in empty <item/> nodes.
Finally, to return only the third and fourth products, shift the positional predicate into the for loop argument:
for $prod in //product[position() = 3 or position() = 4]
return <item>{ $prod }</item>
(and apply data(...) as needed, but I'd guess it won't yield the results you expect here).
How to import below XML data into SQL Server table with three columns?
<dataset>
<metadata>
<item name="NAME_LAST" type="xs:string" length="62" />
<item name="NAME_FIRST" type="xs:string" length="62" />
<item name="NAME_MIDDLE" type="xs:string" length="32" />
</metadata>
<data>
<row>
<value>SMITH</value>
<value>MARY</value>
<value>N</value>
</row>
<row>
<value>SMITH2</value>
<value>MARY2</value>
<value>N2</value>
</row>
</data>
</dataset>
Try this:
DECLARE #input XML = '<dataset>
<metadata>
<item name="NAME_LAST" type="xs:string" length="62" />
<item name="NAME_FIRST" type="xs:string" length="62" />
<item name="NAME_MIDDLE" type="xs:string" length="32" />
</metadata>
<data>
<row>
<value>SMITH</value>
<value>MARY</value>
<value>N</value>
</row>
<row>
<value>SMITH2</value>
<value>MARY2</value>
<value>N2</value>
</row>
</data>
</dataset>'
INSERT INTO dbo.YourTable(ColName, ColFirstName, ColOther)
SELECT
Name = XCol.value('(value)[1]','varchar(25)'),
FirstName = XCol.value('(value)[2]','varchar(25)'),
OtherValue = XCol.value('(value)[3]','varchar(25)')
FROM
#input.nodes('/dataset/data/row') AS XTbl(XCol)
Insert XML Data into sql Server table
Declare #retValue1 varchar(50);
Declare #XmlStr XML;
SET #XmlStr='<Customers>
<customer>
<ID>111589</ID>
<FirstName>name1</FirstName>
<LastName>Lname1</LastName>
<Company>ABC</Company>
</customer>
<customer>
<ID>12345</ID>
<FirstName>name2</FirstName>
<LastName>Lname2</LastName>
<Company>ABC</Company>
</customer>
<customer>
<ID>14567</ID>
<FirstName>name3</FirstName>
<LastName>Lname3</LastName>
<Company>DEF</Company>
</customer>
</Customers>';
#retValue='Failed';
INSERT INTO [test_xmlinsert](
[id],
[firstName],
[lastName],
[company]
)
SELECT
COALESCE([Table].[Column].value('ID[1]', 'int'),0) as 'ID',
[Table].[Column].value('FirstName [1]', 'varchar(50)') as ' FirstName ',
[Table].[Column].value(' LastName[1]', 'varchar(50)') as ' LastName',
[Table].[Column].value(' Company [1]', 'varchar(50)') as ' Company'
FROM #XmlStr.nodes('/ Customers / customer') as [Table]([Column])
IF(##ROWCOUNT > 0 )
SET #retValue='SUCCESS';
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
I am writing SQL query to get output as below . I am not using any tables from database.
A query to get the desired output as
<Property ID="0" Name="Color" NumOfItems="11">
<Item ID="0" Name="D"/>
<Item ID="1" Name="E"/>
<Item ID="2" Name="F"/>
<Item ID="3" Name="G"/>
<Item ID="4" Name="H"/>
<Item ID="5" Name="I"/>
<Item ID="6" Name="J"/>
<Item ID="7" Name="K"/>
<Item ID="8" Name="L"/>
<Item ID="9" Name="M"/>
<Item ID="10" Name="N"/>
</Property>
I tried as this
SELECT
(
SELECT '0' AS 'Item/#ID','D' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '1' AS 'Item/#ID','E' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '2' AS 'Item/#ID','F' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '3' AS 'Item/#ID','G' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '4' AS 'Item/#ID','H' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '5' AS 'Item/#ID','I' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '6' AS 'Item/#ID','J' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '7' AS 'Item/#ID','K' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '8' AS 'Item/#ID','L' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '9' AS 'Item/#ID','M' AS 'Item/#Name' FOR XML PATH(''), TYPE ),
(SELECT '10' AS 'Item/#ID','N' AS 'Item/#Name' FOR XML PATH(''), TYPE )
FOR XML PATH(''),
ROOT('Property'),TYPE
I am not using any tables from database
Well just SELECT it...
SELECT CAST ('<Property ID="0" Name="Color" NumOfItems="11">
<Item ID="0" Name="D"/>
<Item ID="1" Name="E"/>
<Item ID="2" Name="F"/>
<Item ID="3" Name="G"/>
<Item ID="4" Name="H"/>
<Item ID="5" Name="I"/>
<Item ID="6" Name="J"/>
<Item ID="7" Name="K"/>
<Item ID="8" Name="L"/>
<Item ID="9" Name="M"/>
<Item ID="10" Name="N"/>
</Property>' AS XML)
1)
SELECT *
FROM (VALUES (0, 'Color', 11)) Property(ID, Name, NumOfItems)
JOIN (VALUES (0,0,'D'), (0,1,'E'), (0,2,'F')) Item(PropertyID,ID,Name)
ON Property.ID = Item.PropertyID
FOR XML AUTO
Output:
<Property ID="0" Name="Color" NumOfItems="11">
<Item PropertyID="0" ID="0" Name="D" />
<Item PropertyID="0" ID="1" Name="E" />
<Item PropertyID="0" ID="2" Name="F" />
</Property>
2)
SELECT *,
(SELECT * FROM (VALUES (0,'D'), (1, 'E'), (2, 'F')) MamboJambo("#ID", "#Name") FOR XML PATH('Item'),TYPE)
FROM (VALUES (0,'Color',11)) CocoJambo("#ID", "#Name", "#NumOfItems")
FOR XML PATH('Property')
3)
SELECT CONVERT(XML, N'<Property ID="0" Name="Color" NumOfItems="11">
<Item ID="0" Name="D"/>
<Item ID="1" Name="E"/>
<Item ID="2" Name="F"/>
</Property>').query(N'
for $x in (/Property)
return
<Property ID="{$x/#ID}" Name="{$x/#Name}" NumOfItems="{$x/#NumOfItems}" >
{for $y in ($x/Item) return $y}
</Property>
');