在 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
我已经开始在 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 |