sql - 我有以下 XML,我需要将其存储在 sql 表中
问题描述
我需要标签 ServerName、DBName、UserName、RoleName。我无法访问这些标签,因为 xml 的第一部分给我带来了麻烦
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>Selected.System.Object</T>
<T>System.Management.Automation.PSCustomObject</T>
<T>System.Object</T>
</TN>
<MS>
<S N="ServerName">DDW</S>
<S N="DBName">dwSeriesOLAP</S>
<S N="UserName">123Z</S>
<S N="RoleName">test1</S>
</MS>
</Obj>
<Obj RefId="1">
<TNRef RefId="0" />
<MS>
<S N="ServerName">DDW</S>
<S N="DBName">dwSeriesOLAP</S>
<S N="UserName">1234</S>
<S N="RoleName">test2</S>
</MS>
</Obj>
<Obj RefId="2">
<TNRef RefId="0" />
<MS>
<S N="ServerName">DDW</S>
<S N="DBName">dwSeriesOLAP</S>
<S N="UserName">12345aa</S>
<S N="RoleName">test3</S>
</MS>
</Obj>
</Objs>
解决方案
在您的 XML 中有两种不同的结构:
DECLARE @xml XML=
N'<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>Selected.System.Object</T>
<T>System.Management.Automation.PSCustomObject</T>
<T>System.Object</T>
</TN>
<MS>
<S N="ServerName">DDW</S>
<S N="DBName">dwSeriesOLAP</S>
<S N="UserName">123Z</S>
<S N="RoleName">test1</S>
</MS>
</Obj>
<Obj RefId="1">
<TNRef RefId="0" />
<MS>
<S N="ServerName">DDW</S>
<S N="DBName">dwSeriesOLAP</S>
<S N="UserName">1234</S>
<S N="RoleName">test2</S>
</MS>
</Obj>
<Obj RefId="2">
<TNRef RefId="0" />
<MS>
<S N="ServerName">DDW</S>
<S N="DBName">dwSeriesOLAP</S>
<S N="UserName">12345aa</S>
<S N="RoleName">test3</S>
</MS>
</Obj>
</Objs>';
--查询你的第一个元素<TN>
WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/powershell/2004/04')
SELECT obj.value('@RefId','int') AS ObjectId
,obj.value('(TN/@RefId)[1]','int') AS TNId
,t.value('text()[1]','nvarchar(max)') AS T_Content
FROM @xml.nodes('/Objs/Obj[TN]') A(obj) --<-- see the predicate for `[TN]`
CROSS APPLY A.obj.nodes('TN/T') B(t);
--如果你可以确定,前一个的替代方案,只有一个<TN>
元素:
WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/powershell/2004/04')
SELECT @xml.value('(/Objs/Obj[TN]/@RefId)[1]','int') AS ObjectId
,@xml.value('(/Objs/Obj[TN]/TN/@RefId)[1]','int') AS TNId
,t.value('text()[1]','nvarchar(max)') AS T_Content
FROM @xml.nodes('/Objs/Obj[TN]/TN/T') A(t);
--重复<MS><S>
元素的查询
WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/powershell/2004/04')
SELECT obj.value('@RefId','int') AS ObjectId
--if appropriate you might use COALLESCE for the TN-ids
,obj.value('(TN/@RefId)[1]','int') AS TNId
,obj.value('(TNRef/@RefId)[1]','int') AS TNRefId
,obj.value('(MS/S[@N="ServerName"]/text())[1]','nvarchar(max)') AS ServerName
,obj.value('(MS/S[@N="DBName"]/text())[1]','nvarchar(max)') AS DBName
,obj.value('(MS/S[@N="UserName"]/text())[1]','nvarchar(max)') AS UserName
,obj.value('(MS/S[@N="RoleName"]/text())[1]','nvarchar(max)') AS RoleName
FROM @xml.nodes('/Objs/Obj') A(obj)
--还有一个单独检索每个嵌入式结构。这允许逐步的方法(例如,使用中间临时表)。
WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/powershell/2004/04')
,TheObjects AS
(
SELECT obj.value('@RefId','int') AS ObjectId
,obj.query('TN') AS TN_Element
,obj.query('TNRef') AS TNRef_Element
,obj.query('MS') AS MS_Element
FROM @xml.nodes('/Objs/Obj') A(obj)
)
SELECT *
FROM TheObjects;
简而言之:
- 我们需要声明现有的默认命名空间
- 我们
.nodes()
用来潜入重复元素 - 我们用于
.value()
检索数据(@xml
直接来自或来自来自的 Xml 片段.nodes()
)。 - 我们
.query()
用来检索 Xml 片段。
推荐阅读
- sql - 需要有关管理 sqlite 文件的指南
- cucumber - 如何获取黄瓜中的当前重试次数
- go - 0777权限写入文件失败
- css - ion-item 上的关键帧动画没有平滑过渡
- java - 如何从子键中获取值并根据其他子键中的键
- r - 在超过 5 个变量上应用 R 中的卡方检验并找到 p 值
- excel - 将多个系列添加到散点图的 VBA 代码 - 运行时 1004 错误
- javascript - 如何在功能组件中混合使用 useCallback 和 useRef
- amazon-web-services - 如何安排 AWS Lambda 在凌晨 12:00:00 准确运行(秒级精度)?
- mongodb - Does querying certain fields only save query time in mongodb?