TSQL XML定位特定块

时间:2017-12-07 06:06:42

标签: sql-server xml tsql xquery

DECLARE @XMLData XML

SET @XMLData = '<ArrayOfAttributeValueDO>
      <AttributeValueDO>
        <AttributeID>421</AttributeID>
        <AttributeValue>100% cotton pre-shrunk drill</AttributeValue>
      </AttributeValueDO>
      <AttributeValueDO>
        <AttributeID>422</AttributeID>
        <AttributeValue>190gsm</AttributeValue>
      </AttributeValueDO>
      <AttributeValueDO>
        <AttributeID>1221</AttributeID>
        <AttributeValue>Long Sleeve</AttributeValue>
      </AttributeValueDO>
      <AttributeValueDO>
        <AttributeID>1481</AttributeID>
        <AttributeValue>No</AttributeValue>
      </AttributeValueDO>
    </ArrayOfAttributeValueDO>'

鉴于上述示例,如何通过搜索<AttributeValueDO><AttributeID>来获取特定<AttributeValue>

我有点期待这样的语法,但在&#34; []&#34;之间有错误。 事实上,我正在努力获取任何<AttributeValueDO> attributeID为422,而attributeValue包含&#39; gsm&#39;

DECLARE @strAttributeID VARCHAR(1000) = '422'
DECLARE @strAttributeValue VARCHAR(1000) = '190gsm'

SELECT [AttributeValueXML] 
FROM [dbo].[tbl_Stock_Master_AttributeValue] 
WHERE [AttributeValueXML].exist('(/ArrayOfAttributeValueDO/AttributeValueDO[AttributeID=sql:variable("@strAttributeID") && AttributeValue=sql:variable("@strAttributeValue")])') = 1

2 个答案:

答案 0 :(得分:3)

有一种可能性是将整个批次作为派生表阅读,并在最后放置过滤器WHERE(如另一个答案所示)。但是 - 至少在我看来 - 将过滤器直接放在XQuery

中效率更高

如果你可以肯定,只有一次出现,试试这个:

DECLARE @strAttributeID VARCHAR(1000) = '422'
DECLARE @strAttributeValue VARCHAR(1000) = '190gsm'
SELECT @XMLData.value(N'(/ArrayOfAttributeValueDO
                         /AttributeValueDO[(AttributeID/text())[1]=sql:variable("@strAttributeID") 
                                            and contains((AttributeValue/text())[1],sql:variable("@strAttributeValue"))]
                         /AttributeValue/text())[1]','nvarchar(max)');

如果可能有更多的出现,请使用.nodes()来获取拟合节点的派生表,并使用.value()从每个子节点中获取所需的值:

SELECT Attr.value('(AttributeValue/text())[1]','nvarchar(max)')
FROM @XMLData.nodes(N'/ArrayOfAttributeValueDO
                      /AttributeValueDO[(AttributeID/text())[1]=sql:variable("@strAttributeID") 
                                            and contains((AttributeValue/text())[1],sql:variable("@strAttributeValue"))]') AS Searched(Attr);

提示:使用(SomeElement/text())[1]SomeElement[1]/text()[1]比简单SomeElement[1]稍快一些。在你的情况下,它将返回相同的(具有更好的可读性)......但是:总的来说,我建议尽可能具体。 Find more details on /text() here

答案 1 :(得分:0)

您可以尝试这样的事情:

DECLARE @AttributeID INT = 422
DECLARE @AttrValue VARCHAR(20) = 'gsm'

SELECT
    xc.query('.')
FROM
    @XMLData.nodes('/ArrayOfAttributeValueDO/AttributeValueDO') AS XT(XC)
WHERE
    xc.value('(AttributeID)[1]', 'int') = @AttributeID 
    AND xc.value('(AttributeValue)[1]', 'varchar(50)') LIKE '%' + @AttrValue + '%'

这基本上为您提供了这两个标准适用的任何XML片段(整个<AttributeValueDO> XML元素)。