sql-server - 查询 XML 列
问题描述
我有一个采用这种格式的 XML 列:
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>SubscriberBalanceBefore</name>
<value>
<string>0.0</string>
</value>
</member>
<member>
<name>TimeStamp</name>
<value>
<dateTime.iso8601>20200812T12:31:10</dateTime.iso8601>
</value>
</member>
<member>
<name>Subsc riberMSISDN</name>
<value>
<string>83000000</string>
</value>
</member>
<member>
<name>TransactionID</name>
<value>
<string>8035768</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
我希望得到如下表所示的结果:
-------------------------
name | TransactionID
----------|---------------
830000000 | 8035768
我尝试过使用CROSS
,OUTER APPLY
但它不起作用:
SELECT
X.Y.value('(name)[3]', 'VARCHAR(max)') as NAME_FIELD,
X.Y.value('(value/string)[4]', 'varchar(max)') DATA_CONTENT
FROM [TABLE] T
OUTER APPLY T.xmlIn.nodes('methodResponse/params/param/value/struct/member') as X(Y)
它不会给出错误,但会为两个字段返回空值。有人可以帮忙吗?
解决方案
您的单例标识符不正确。例如(name)[3]
将引用每个name
节点中的第三个节点。每个成员只有 1 个节点,因此值。member
name
NULL
您需要分别引用第 3 个和第 4member
个节点:
DECLARE @XML xml = '<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>SubscriberBalanceBefore</name>
<value>
<string>0.0</string>
</value>
</member>
<member>
<name>TimeStamp</name>
<value>
<dateTime.iso8601>20200812T12:31:10</dateTime.iso8601>
</value>
</member>
<member>
<name>Subsc riberMSISDN</name>
<value>
<string>83000000</string>
</value>
</member>
<member>
<name>TransactionID</name>
<value>
<string>8035768</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>'
SELECT X.Y.value('(member[3]/value/string/text())[1]', 'varchar(max)') as NAME_FIELD, --Does this need to be a varchar(MAX)? Why not an int?
X.Y.value('(member[4]/value/string/text())[1]', 'varchar(max)') DATA_CONTENT --Does this need to be a varchar(MAX)? Why not an int?
FROM (VALUES(@XML))T(xmlIn)
OUTER APPLY T.xmlIn.nodes('methodResponse/params/param/value/struct') as X(Y);
但是请注意,上述解决方案取决于节点的序数位置。使用 XPATH 和一些布尔逻辑,您可以避免这种情况:
SELECT X.Y.value('(member[name/text()="Subsc riberMSISDN"]/value/string/text())[1]', 'int') as NAME_FIELD,
X.Y.value('(member[name/text()="TransactionID"]/value/string/text())[1]', 'int') DATA_CONTENT
FROM (VALUES(@XML))T(xmlIn)
OUTER APPLY T.xmlIn.nodes('methodResponse/params/param/value/struct') as X(Y);
推荐阅读
- sql - 我们可以在 SQL Server 中为每个计数使用多个计数(列)和 where cluase
- python - 我如何删除 python 2.7,因为我已经在 ubuntu 上安装了 3.6.5?
- go - 如何避免在连续错误处理中重复自己
- python - 如何调试通过 Jenkins 运行 shell 脚本的问题?
- csom - 如何通过 csom 代码使用保存的模板创建任务列表
- block - 如何以编程方式显示自定义块
- jenkins - 詹金斯管道 - 无法在空对象上调用方法阶段()
- swift - 集合视图单元格动态高度问题
- java - 获取响应的总页数
- go - Golang Program leaking memory