【问题标题】:Query XML Column查询 XML 列
【发布时间】:2020-08-13 11:30:05
【问题描述】:

我有一个这种格式的 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

我尝试过使用CROSSOUTER 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)

它不会给出错误,但会为两个字段返回空值。有人可以帮忙吗?

【问题讨论】:

  • 上面的给出一个错误,特别是XQuery [T.xmlIn.value()]: Invalid source character '\' (0x5c)。应该是value/string(正斜杠,而不是反斜杠)
  • 谢谢@Larnu,但这是拼写错误。我在查询中使用了“\”。

标签: sql-server xml


【解决方案1】:

您的单例标识符不正确。例如(name)[3] 将引用member 节点中每个 中的第三个name 节点。每个成员只有 1 个 name 节点,因此是 NULL 值。

你需要分别引用第3个和第4个member节点:

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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2013-08-18
    • 2012-10-18
    • 2011-07-04
    • 2014-08-10
    相关资源
    最近更新 更多