【问题标题】:Query XML in SQL Server with sub tags in one row在 SQL Server 中使用一行中的子标签查询 XML
【发布时间】:2020-10-09 12:19:26
【问题描述】:

我是 XML 新手,我被要求编写一个 T-SQL 查询,该查询将使用 XML 文件并将其转换为带有 SQL Server 的表/视图。虽然实际的 XML 是客户端数据,但我尝试将 XML 文件简化为以下示例。

我认为这个想法类似于子查询,但对于 XML,我将仅在一行中显示每个案例的所有步骤。

 <testcases>
  <testcase>
    <testcasename> first </testcasename>
    <MediaType> Voice </MediaType>
    <steps>
      <CallSteps>
        <Step>
          <StepNo>1</StepNo>
          <description> first step </description>
          <StepNo>2</StepNo>
          <description> second step </description>
        </Step>
      </CallSteps>
    </steps>
  </testcase>
  <testcase>
    <testcasename> second </testcasename>
    <MediaType> Chat </MediaType>
    <steps>
      <CallSteps>
        <Step>
          <StepNo>1</StepNo>
          <description> first step </description>
          <StepNo>2</StepNo>
          <description> second step </description>
          <StepNo>3</StepNo>
          <description> Third step </description>
        </Step>
      </CallSteps>
    </steps>
  </testcase>
  <testcase>
    <testcasename> Third </testcasename>
    <MediaType> Voice </MediaType>
    <steps>
      <CallSteps>
        <Step>
          <StepNo>1</StepNo>
          <description> first step </description>
        </Step>
      </CallSteps>
    </steps>
  </testcase>
</testcases>

我想显示在下表中

步数可以尽可能多(~100)

到目前为止,我已经来到这里-

    select @xml
declare @idoc int
EXEC sp_xml_preparedocument @idoc OUTPUT, @xml; 
select *  from openxml(@idoc, '/testcases/testcase',2)
with (
testcasename nvarchar(10),
MediaType nvarchar(10),
steps  xml
)

下面的输出

请帮忙

【问题讨论】:

  • 不要使用那种真的老方法。 XQUERY 至少从 SQL Server 2008 年(甚至可能是 2005 年)就已经存在。
  • XQuery 从 SQL Server 2005 开始可用

标签: sql-server xml tsql


【解决方案1】:

停止使用那种真的旧的读取 XML 的方法;出于向后兼容性的原因,它实际上只是仍在 SQL Server 中。而是使用使用 XQUERY 的“较新”(它仍然存在至少 12 年)方法。

如果您使用几个 nodes 引用,则可以使用 value 函数获取实际值:

DECLARE @XML xml = '<testcases>
  <testcase>
    <testcasename> first </testcasename>
    <MediaType> Voice </MediaType>
    <steps>
      <CallSteps>
        <Step>
          <StepNo>1</StepNo>
          <description> first step </description>
          <StepNo>2</StepNo>
          <description> second step </description>
        </Step>
      </CallSteps>
    </steps>
  </testcase>
  <testcase>
    <testcasename> second </testcasename>
    <MediaType> Chat </MediaType>
    <steps>
      <CallSteps>
        <Step>
          <StepNo>1</StepNo>
          <description> first step </description>
          <StepNo>2</StepNo>
          <description> second step </description>
          <StepNo>3</StepNo>
          <description> Third step </description>
        </Step>
      </CallSteps>
    </steps>
  </testcase>
  <testcase>
    <testcasename> Third </testcasename>
    <MediaType> Voice </MediaType>
    <steps>
      <CallSteps>
        <Step>
          <StepNo>1</StepNo>
          <description> first step </description>
        </Step>
      </CallSteps>
    </steps>
  </testcase>
</testcases>';

SELECT tcs.tc.value('(testcasename/text())[1]','varchar(20)') AS testcasename,
       tcs.tc.value('(MediaType/text())[1]','varchar(20)') AS MediaType,
       CS.S.value('(StepNo/text())[1]','int') AS StepNo1,
       CS.S.value('(StepNo/text())[2]','int') AS StepNo2,
       CS.S.value('(StepNo/text())[3]','int') AS StepNo3,
       CS.S.value('(description/text())[1]','varchar(20)') AS description1,
       CS.S.value('(description/text())[2]','varchar(20)') AS description2,
       CS.S.value('(description/text())[3]','varchar(20)') AS description3
FROM (VALUES(@XML))V(X)
     CROSS APPLY V.X.nodes('/testcases/testcase')tcs(tc)
     CROSS APPLY tcs.tc.nodes('./steps/CallSteps/Step')CS(S);

【讨论】:

  • 是的,这是一种方法,但是,就像我说的,步骤数可以达到 100 步。有没有一种方法可以基于 XML 动态扩展 CS.S.Value过关了吗?
  • 如果您需要动态列数,则需要动态 SQL,@ShamvilKazmi。因此,我建议以标准化形式处理数据,每步有 1 行,而不是 1 列。否则,如果您必须有列,而不是动态 SQL,则需要写出所有 100 (x2) 个引用。
  • 您对数据进行规范化是对的,我将尝试说服我的客户这样做。如果他们不同意,我将尝试使用动态 SQL 编写,如果我遇到困难,那么将就这个 XML 示例提出一个单独的问题。我真的很感谢你的帮助拉努
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2012-04-17
  • 2013-01-15
  • 2013-08-18
  • 2012-10-18
  • 1970-01-01
相关资源
最近更新 更多