【问题标题】:TSQL XML locate particular block(s)TSQL XML 定位特定块
【发布时间】:2017-12-07 06:06:41
【问题描述】:
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>'

鉴于上述示例,我如何通过搜索&lt;AttributeID&gt;&lt;AttributeValue&gt; 来获得特定的&lt;AttributeValueDO&gt;

我有点期待这样的语法,但在“[]”之间有错误 事实上,我正在尝试获取任何 &lt;AttributeValueDO&gt; 与 422 的 attributeIDattributeValue 包含“gsm”字样

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

【问题讨论】:

  • 不是and 而不是&amp;&amp; 吗?另外,请在您的问题中包含您收到的完整错误消息(为了便于阅读,请加引号)。

标签: sql-server xml tsql xquery


【解决方案1】:

一个机会是将整个文件作为派生表阅读,并将您的过滤器与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

【讨论】:

    【解决方案2】:

    你可以试试这样的:

    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 片段(整个 &lt;AttributeValueDO&gt; XML 元素)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-28
      • 2013-02-10
      • 2016-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      • 2012-05-21
      相关资源
      最近更新 更多