在 SQL 服务器中粉碎 XML 文档

Shred XML document in SQL Server

我已经开始在 SQL 服务器中粉碎我的 XML 文档,但我仍然不知道如何退出 tback。我目前只能将 inventorymodelday 下的 3 个元素获取到每一行。你如何在级别中“备份”以便我可以将 inventorymodel id 应用于每一行(在本例中为“默认”)?

SELECT
    InvModels.inventorymodelday.query('DemandPercent').value('.', 'float'),
    InvModels.inventorymodelday.query('StocksPerDay').value('.', 'int'),
    InvModels.inventorymodelday.query('Supply').value('.', 'int')
FROM(
    SELECT CAST(InvModels AS xml)
    FROM OPENROWSET(
        BULK '***.xml', SINGLE_BLOB) AS T(InvModels)
) AS T(InvModels)
CROSS APPLY InvModels.nodes('inventorymodels/inventorymodel/inventorymodeldays/inventorymodelday') AS InvModels(inventorymodelday)
<inventorymodels count="1">
  <inventorymodel id="Default">
    <inventorymodeldays count="7">
      <inventorymodelday>
        <DemandPercent>15.0000009536743</DemandPercent>
        <StocksPerDay>0</StocksPerDay>
        <Supply>0</Supply>
      </inventorymodelday>
      <inventorymodelday>
        <DemandPercent>10</DemandPercent>
        <StocksPerDay>0</StocksPerDay>
        <Supply>1</Supply>
      </inventorymodelday>
      <inventorymodelday>
        <DemandPercent>11</DemandPercent>
        <StocksPerDay>0</StocksPerDay>
        <Supply>0</Supply>
      </inventorymodelday>
      <inventorymodelday>
        <DemandPercent>12</DemandPercent>
        <StocksPerDay>0</StocksPerDay>
        <Supply>0</Supply>
      </inventorymodelday>
      <inventorymodelday>
        <DemandPercent>13</DemandPercent>
        <StocksPerDay>0</StocksPerDay>
        <Supply>0</Supply>
      </inventorymodelday>
      <inventorymodelday>
        <DemandPercent>19</DemandPercent>
        <StocksPerDay>1</StocksPerDay>
        <Supply>1</Supply>
      </inventorymodelday>
      <inventorymodelday>
        <DemandPercent>20</DemandPercent>
        <StocksPerDay>0</StocksPerDay>
        <Supply>0</Supply>
      </inventorymodelday>
    </inventorymodeldays>
  </inventorymodel>
</inventorymodels>

类似的东西可能有用

SELECT
    InvModel.inventorymodel.value('@id', 'varchar(100)'),
    InvModels.inventorymodelday.query('DemandPercent').value('.', 'float'),
    InvModels.inventorymodelday.query('StocksPerDay').value('.', 'int'),
    InvModels.inventorymodelday.query('Supply').value('.', 'int')
FROM(
    SELECT CAST(InvModels AS xml)
    FROM OPENROWSET(
        BULK '***.xml', SINGLE_BLOB) AS T(InvModels)
) AS T(InvModels)
CROSS APPLY InvModels.nodes('inventorymodels/inventorymodel') AS InvModel(inventorymodel)
cross apply invModel.inventoryModel.nodes('inventorymodeldays/inventorymodelday') as InvModels(inventorymodelday)

这里是如何通过模拟 one-to-many 关系的双 CROSS APPLY 子句来处理它。

要点:

  • 无需使用.query()方法。只需 .value() 方法就足够了。
  • 出于性能原因使用 XPath ../text() 表达式。

SQL

;WITH rs (xmldata) AS
(
    SELECT TRY_CAST(BulkColumn AS XML) AS BulkColumn 
    FROM OPENROWSET(BULK 'e:\Temp\owneyjs.xml', SINGLE_BLOB) AS x
)

SELECT c.value('@id', 'VARCHAR(30)') AS inventorymodel
    , x.value('(DemandPercent/text())[1]','FLOAT') AS DemandPercent
    , x.value('(StocksPerDay/text())[1]', 'INT') AS StocksPerDay
    , x.value('(Supply/text())[1]', 'INT') AS Supply
FROM rs
CROSS APPLY xmldata.nodes('/inventorymodels/inventorymodel') AS t1(c)
CROSS APPLY t1.c.nodes('inventorymodeldays/inventorymodelday') AS t2(x);

输出

+----------------+------------------+--------------+--------+
| inventorymodel |  DemandPercent   | StocksPerDay | Supply |
+----------------+------------------+--------------+--------+
| Default        | 15.0000009536743 |            0 |      0 |
| Default        |               10 |            0 |      1 |
| Default        |               11 |            0 |      0 |
| Default        |               12 |            0 |      0 |
| Default        |               13 |            0 |      0 |
| Default        |               19 |            1 |      1 |
| Default        |               20 |            0 |      0 |
+----------------+------------------+--------------+--------+

假设你你的XML变量@input,你可以试试这个:

SELECT
    ModelId = xc.value('(../../@id)[1]', 'varchar(25)'),
    DemandPercent = xc.value('(DemandPercent)[1]', 'decimal(25,15)'),
    StocksPerDay = xc.value('(StocksPerDay)[1]', 'int'),
    Supply = xc.value('(Supply)[1]', 'int')
FROM
    @input.nodes('/inventorymodels/inventorymodel/inventorymodeldays/inventorymodelday') as XT(XC)

这将 return 这样的结果:

ModelId DemandPercent StocksPerDay Supply
Default 15.000000953674300 0 0
Default 10.000000000000000 0 1
Default 11.000000000000000 0 0
Default 12.000000000000000 0 0
Default 13.000000000000000 0 0
Default 19.000000000000000 1 1
Default 20.000000000000000 0 0