[英]How to return the value that exists in SQL Server XPath?
在Stackoverflow上的某个地方有一个问题,尽管我现在找不到,但提醒发布者.value
不会返回.exist
s的值。
这是因为.value
始终写为要求[1]
项,而.exist
到处都是。
给定一个假设的xml文档,其中包含两个客户:
<Customer>
<Name>Ian Boyd</Name>
<IDInfo>
<IDType>1</IDType>
</IDInfo>
</Customer>
<Customer>
<Name>Kirsten</Name>
<IDInfo>
<IDType>3</IDType>
<IDOtherDescription>Firearms Certificate</IDOtherDescription>
</IDInfo>
</Customer>
我想为IDType为3
(其他)的任何客户返回Name
, IDType
和IDOtherDescription
:
DECLARE @xml XML;
SET @xml =
'<Customer>
<Name>Ian Boyd</Name>
<IDInfo>
<IDType>1</IDType>
</IDInfo>
</Customer>
<Customer>
<Name>Kirsten</Name>
<IDInfo>
<IDType>3</IDType>
<IDOtherDescription>Firearms Certificate</IDOtherDescription>
</IDInfo>
</Customer>'
--Wrap it up in a table, cause it makes it look more like my real situation
;WITH BatchReports AS (
SELECT @xml AS BatchFileXml
)
SELECT
BatchFileXml.value('(//Name)[1]', 'varchar(50)') AS Name,
BatchFileXml.value('(//IDType)[1]', 'varchar(50)') AS IDType,
BatchFileXml.value('(//IDOtherDescription)[1]', 'varchar(50)') AS IDOtherDescription,
*
FROM BatchReports
--WHERE BatchFileXml.value('(//IDType)[1]', 'varchar(50)') = '3'
WHERE BatchFileXml.exist('//IDType[text()="3"]')=1
由于.exist
满足 ,它返回一行:
Name IDType IDOtherDescription
-------- ------ --------------------
Ian Boyd 1 Firearms Certificate
除非那不是我想要的。 我想要IDType = 3
的值。
在有多个IDType
条目的情况下,事情变得更加复杂:
<Customer>
<Name>Ian Boyd</Name>
<IDInfo>
<IDType>1</IDType>
</IDInfo>
</Customer>
<Customer>
<Name>Kirsten</Name>
<IDInfo>
<IDType>1</IDType>
</IDInfo>
<IDInfo>
<IDType>2</IDType>
</IDInfo>
<IDInfo>
<IDType>4</IDType>
</IDInfo>
<IDInfo>
<IDType>3</IDType>
<IDOtherDescription>Firearms Certificate</IDOtherDescription>
</IDInfo>
</Customer>
在其他级别可以找到/IDInfo
节点时,甚至更加复杂:
<Customer>
<Name>Ian Boyd</Name>
<IDInfo>
<IDType>1</IDType>
</IDInfo>
<ThirdPartyInfo>
<IDInfo>
<IDType>3</IDType>
<IDOtherDescription>Sherrif Badge</IDOtherDescription>
</IDInfo>
</ThirdPartyInfo>
</Customer>
<Customer>
<Name>Kirsten</Name>
<IDInfo>
<IDType>1</IDType>
</IDInfo>
<IDInfo>
<IDType>2</IDType>
</IDInfo>
<IDInfo>
<IDType>4</IDType>
</IDInfo>
<IDInfo>
<IDType>3</IDType>
<IDOtherDescription>Firearms Certificate</IDOtherDescription>
</IDInfo>
</Customer>
最终结果是相同的。 我需要一个查询以返回exist
的values
:
Name IDType IDOtherDescription
-------- ------ --------------------
Ian Boyd 3 Sherrif Badge
Kirsten 3 Firearms Certificate
当我两年前设计系统并选择使用XML
数据类型时,我认为在紧急情况下它将很有用。 我可以使用一些XPath来过滤原始xml。 我忘记了XPath和SQL Server中的XPath是多么不可能。 盯着文档和网站四个小时; 我饿又累。
您可以尝试以下查询:
;WITH BatchReports AS (
SELECT @xml AS BatchFileXml
)
SELECT a.BatchXml.value('(Name)[1]', 'varchar(50)') AS Name,
a.BatchXml.value('(IDInfo/IDType)[1]', 'varchar(50)') AS IDType,
a.BatchXml.value('(IDInfo/IDOtherDescription)[1]', 'varchar(50)') AS IDOtherDescription
FROM BatchReports b
CROSS APPLY b.BatchFileXml.nodes('Customer') A(BatchXml)
WHERE a.BatchXml.exist('IDInfo/IDType[text()=3]')=1
这是从所有XML中检索必要信息的查询。
;WITH BatchReports AS (
SELECT @xml AS BatchFileXml
)
SELECT A.BatchXml.value('(Name)[1]', 'varchar(50)') AS Name,
B.BatchXml.value('(IDType)[1]', 'varchar(50)') AS IDType,
B.BatchXml.value('(IDOtherDescription)[1]', 'varchar(50)') AS IDOtherDescription
FROM BatchReports X
CROSS APPLY X.BatchFileXml.nodes('Customer') A(BatchXml)
CROSS APPLY A.BatchXml.nodes('//IDInfo') B(BatchXml)
WHERE A.BatchXml.exist('IDInfo/IDType[text()=3]')=1
AND B.BatchXml.exist('IDType[text()=3]')=1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.