sql 在SQL Server中粉碎XML的节点方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql 在SQL Server中粉碎XML的节点方法相关的知识,希望对你有一定的参考价值。

-- you can use the nodes method to take a piece of XML code and get a relational rowset based on the XML. The steps used are to 1) place the XML into a variable of the type XML (in this case the variable is @x), and 2) SELECT using the nodes method to return XML based on the XPath written out in the nodes method.
DECLARE @x XML;
SET @x = '<?xml version="1.0" encoding="ISO-8859-1"?>
<order id="123456" date="2015-01-01">
  <salesperson id="123">
    <name>Naomi Sharp</name>
  </salesperson>
  <customer id="921">
    <name>Dan Drayton</name>
  </customer>
  <items>
    <item id="268" quantity="2"/>
    <item id="561" quantity="1"/>
    <item id="127" quantity="2"/>
  </items>
</order>';

-- use the nodes method to return XML
SELECT NodesResultTable.ColumnToHoldtheXML.query('.') AS ItemXML
FROM @x.nodes('/order/items/item') AS NodesResultTable(ColumnToHoldtheXML);

/* Results from the query above (assuming there are three item elements in the node you specified, it will return three rows in the resultset containing the XML for each of those elements)
ItemXML
<item id="268" quantity="2" />
<item id="561" quantity="1" />
<item id="127" quantity="2" />
*/

-------------------------------------------------------------------
-- EXAMPLE OF THE NODES METHOD SHOWN ABOVE TO RETURN XML RESULTS --
-------------------------------------------------------------------

-- from the NodesResultTable and the ColumnToHoldtheXML column (definied in the row below), use the query method to return the root node (as deterimined by the '.'), and call the resulting column ItemXML
SELECT NodesResultTable.ColumnToHoldtheXML.query('.') AS ItemXML
-- FROM the XML-containing variable @x, use the nodes method looking for the path '/order/items/item' (looking for the item element), and return it as a table called NodesResultTable, with a column called ColumnToHoldtheXML
FROM @x.nodes('/order/items/item') AS NodesResultTable(ColumnToHoldtheXML);

--------------------------------------------------------------------------------
-- EXAMPLE OF THE NODES METHOD SHOWN ABOVE TO RETURN RELATIONAL (SQL) RESULTS --
--------------------------------------------------------------------------------

-- rather than returning XML, you can return relational data using the nodes method

DECLARE @x XML;
SET @x = '<?xml version="1.0" encoding="ISO-8859-1"?>
<order id="123456" date="2015-01-01">
  <salesperson id="123">
    <name>Naomi Sharp</name>
  </salesperson>
  <customer id="921">
    <name>Dan Drayton</name>
  </customer>
  <items>
    <item id="268" quantity="2"/>
    <item id="561" quantity="1"/>
    <item id="127" quantity="2"/>
  </items>
</order>';

-- use nodes method to get a rowset based on the XML elements contained within the variable @x
SELECT	NodesResultTable.ColumnforXML.value('../../@id', 'int') AS OrderID, 
	NodesResultTable.ColumnforXML.value('./@id', 'int') AS ProductID, 
	NodesResultTable.ColumnforXML.value('./@quantity', 'int') AS Quantity
FROM @x.nodes('/order/items/item') AS NodesResultTable(ColumnforXML);

/* Relational results pulled from the XML using the nodes method:
OrderID	ProductID Quantity
123456	268	      2
123456	561	      1
123456	127	      2
*/

-------------------------------------------------------------------------------------
-- DETAIL OF USING THE NODES METHOD SHOWN ABOVE TO RETURN RELATIONAL (SQL) RESULTS --
-------------------------------------------------------------------------------------

-- place your XML into a variable called @x, which is of the type XML
DECLARE @x XML;
SET @x = '<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- root order attribute has namespace order -->
<order id="123456" date="2015-01-01">
  <salesperson id="123">
    <name>Naomi Sharp</name>
  </salesperson>
  <customer id="921">
    <name>Dan Drayton</name>
  </customer>
  <items>
    <item id="268" quantity="2"/>
    <item id="561" quantity="1"/>
    <item id="127" quantity="2"/>
  </items>
</order>';

-- from the ColumnforXML in the NodesResultTable (declared below), use the value method to pull the id attribute of the order element ('../' means go up one level, so since your context node [starting point node] is '/order/items/item', having '../..' means go up two levels to the order element), and name this column OrderID
SELECT	NodesResultTable.ColumnforXML.value('../../@id', 'int') AS OrderID, 
  -- use the value method to pull the id attribute of the 'order/items/item' element ('.' means go stay at the context node, which is '/order/items/item'), and name this column ProductID
	NodesResultTable.ColumnforXML.value('./@id', 'int') AS ProductID, 
	-- use the value method to pull the quantity attribute of the 'order/items/item' element ('.' means go stay at the context node, which is '/order/items/item'), and name this column ProductID
	NodesResultTable.ColumnforXML.value('./@quantity', 'int') AS Quantity
-- from the variable @x, use the nodes method, establishing '/order/items/item' as the context node used above, and return the results in a table called NodesResultTable with an XML-containing column called ColumnforXML
FROM @x.nodes('/order/items/item') AS NodesResultTable(ColumnforXML);


/* Relational results pulled from the XML using the nodes method:
OrderID	ProductID Quantity
123456	268	      2
123456	561	      1
123456	127	      2
*/

-------------------------------------------------------------------------------------
-- ANOTHER EXAMPLE OF NODES METHOD, THIS TIME USING A WHERE CLAUSE TO ONLY PULL CERTAIN ROWS --
-------------------------------------------------------------------------------------
-- INSERT XML INTO VARIABLE
DECLARE @x XML;
SET @x = '  
<HealthData locale="en_US">
 <ExportDate value="2018-11-28 19:41:25"/>
 <Me HKCharacteristicTypeIdentifierDateOfBirth="" HKCharacteristicTypeIdentifierBiologicalSex="HKBiologicalSexNotSet" HKCharacteristicTypeIdentifierBloodType="HKBloodTypeNotSet" HKCharacteristicTypeIdentifierFitzpatrickSkinType="HKFitzpatrickSkinTypeNotSet"/>
 <Record type="HKQuantityTypeIdentifierStepCount" sourceName="iPhone" sourceVersion="9.3.4" device="&lt;&lt;HKDevice: 0x170483520&gt;, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone6,1, software:9.3.4&gt;" unit="count" creationDate="2016-10-28 15:33:43" startDate="2016-10-28 15:21:33" endDate="2016-10-28 15:23:10" value="21"/>
 <Record type="HKQuantityTypeIdentifierDistanceWalkingRunning" sourceName="iPhone" sourceVersion="10.3.1" device="&lt;&lt;HKDevice: 0x170a80190&gt;, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone6,1, software:10.3.1&gt;" unit="mi" creationDate="2018-11-28 19:31:43" startDate="2018-11-28 19:20:02" endDate="2018-11-28 19:23:35" value="0.0338212"/>
 <Record type="HKQuantityTypeIdentifierDistanceWalkingRunning" sourceName="iPhone" sourceVersion="10.3.1" device="&lt;&lt;HKDevice: 0x170a80230&gt;, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone6,1, software:10.3.1&gt;" unit="mi" creationDate="2018-11-28 19:31:43" startDate="2018-11-28 19:23:35" endDate="2018-11-28 19:25:13" value="0.00958776"/>
 <Record type="HKQuantityTypeIdentifierDistanceWalkingRunning" sourceName="iPhone" sourceVersion="10.3.1" device="&lt;&lt;HKDevice: 0x170a802d0&gt;, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone6,1, software:10.3.1&gt;" unit="mi" creationDate="2018-11-28 19:31:43" startDate="2018-11-28 19:29:33" endDate="2018-11-28 19:29:53" value="0.00447387"/>
</HealthData>';
 
-- SELECT DISTANCE ELEMENTS AS RELATIONAL DATA
SELECT	xmlTable.xmlColumn.value('./@type', 'varchar(100)') AS Type
		, xmlTable.xmlColumn.value('./@creationDate', 'datetime') AS CreateDate
		, xmlTable.xmlColumn.value('./@startDate', 'datetime') AS StartDate
		, xmlTable.xmlColumn.value('./@endDate', 'datetime') AS EndDate
		, CAST(xmlTable.xmlColumn.value('./@value', 'varchar(50)') AS DECIMAL(22,4)) AS DistanceMiles
FROM @x.nodes('/HealthData/Record') AS xmlTable(xmlColumn) -- set context node to be used by all value statements above
WHERE xmlTable.xmlColumn.value('./@type', 'varchar(100)') = 'HKQuantityTypeIdentifierDistanceWalkingRunning';

-- SELECT STEPS ELEMENTS AS RELATIONAL DATA
SELECT	xmlTable.xmlColumn.value('./@type', 'varchar(100)') AS Type
		, xmlTable.xmlColumn.value('./@creationDate', 'datetime') AS CreateDate
		, xmlTable.xmlColumn.value('./@startDate', 'datetime') AS StartDate
		, xmlTable.xmlColumn.value('./@endDate', 'datetime') AS EndDate
		, CAST(xmlTable.xmlColumn.value('./@value', 'varchar(50)') AS INT) AS Steps
FROM @x.nodes('/HealthData/Record') AS xmlTable(xmlColumn) -- set context node to be used by all value statements above
WHERE xmlTable.xmlColumn.value('./@type', 'varchar(100)') = 'HKQuantityTypeIdentifierStepCount';

*/

Results:

Type                                              CreateDate              StartDate               EndDate                 DistanceMiles
------------------------------------------------- ----------------------- ----------------------- ----------------------- ---------------------------------------
HKQuantityTypeIdentifierDistanceWalkingRunning    2018-11-28 19:31:43.000 2018-11-28 19:20:02.000 2018-11-28 19:23:35.000 0.0338
HKQuantityTypeIdentifierDistanceWalkingRunning    2018-11-28 19:31:43.000 2018-11-28 19:23:35.000 2018-11-28 19:25:13.000 0.0096
HKQuantityTypeIdentifierDistanceWalkingRunning    2018-11-28 19:31:43.000 2018-11-28 19:29:33.000 2018-11-28 19:29:53.000 0.0045

(3 rows affected)

Type                                              CreateDate              StartDate               EndDate                 Steps
------------------------------------------------- ----------------------- ----------------------- ----------------------- -----------
HKQuantityTypeIdentifierStepCount                 2016-10-28 15:33:43.000 2016-10-28 15:21:33.000 2016-10-28 15:23:10.000 21

*/

以上是关于sql 在SQL Server中粉碎XML的节点方法的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 2017 中粉碎 XML

如何在 SQL 中正确粉碎 XML 文档?

SQL 中 XML 粉碎的替代方案

sql 使用XQuery方法查询,值,存在,节点在SQL Server中查询XML

从 SQL Server 中的 XML 中删除所有空节点

Sql Server 取xml中节点值(传参)