【问题标题】:Change XML node name dynamically to cycle through long list in SQL Server动态更改 XML 节点名称以循环浏览 SQL Server 中的长列表
【发布时间】:2017-12-15 16:50:13
【问题描述】:

你们上次帮了大忙,我对 SQL Server 中的 XML 越来越熟悉了,但我还是个新手。

我最近的挑战是我的节点名称相同,最多 50 次,并且只有一个数字来区分它们:

<QuoteHeaderXML>
  <QuoteHeaderData>
    <QuoteHeader>
      <Configurable01 Value="" Name="Credit Memo" />
      <Configurable02 Value="" Name="Contact Person" />
      <Configurable04 Value="N/A" Name="Fed Ex Rated" />
      <Configurable05 Value="Not Branded" Name="Branding" />
      <Configurable06 Value="100%" Name="Project Status" />
      <Configurable07 Value="" Name="Project Name" />
      <Configurable08 Value="None" Name="Project Manager" />
      <Configurable09 Value="" Name="Shipping Notes" />
      <Configurable10 Value="False" Name="High Profile Order" />
      <Configurable11 Value="New Construction" Name="Project Type" />
      <Configurable12 Value="Single-family" Name="Channel" />
      <Configurable13 Value="US - Texas - Northern" Name="Job Location" />
      <Configurable20 Value="Dealer Warehouse" Name="Delivery Destination" />
    </QuoteHeader>
  </QuoteHeaderData>
</QuoteHeaderXML>

因此,如果我想提取 ConfigurableNN、名称和值的列,我必须编写这 50x 以将它们全部拉入它们存在的单独行中……或者为 50 个中的每一个调用每个最终在 150 多列表格中!我不喜欢这些选项。

相反,我希望编写代码来一次提取 ConfigurableNN、名称和值,但让它根据计数器动态更改节点的数量。但是,我看不到这样做,因为它抱怨 “XML 数据类型方法“值”的参数 1 必须是字符串文字。”。

这是我从我发现但无法工作的帖子中尝试和解决的问题......有任何建议还是这不可能?

WHILE @ConfigCounter <= 50
    BEGIN
        SET @CfgNum = case when @ConfigCounter < 10 then '0' else '' end + cast(@ConfigCounter as varchar(2));

        select t.x.value('(Configurable'+cast(@CfgNum as varchar(2))+'/@Name)[1]','varchar(255)')   ConfigurableFieldName
              ,t.x.value('(Configurable'+cast(@CfgNum as varchar(2))+'/@Value)[1]','varchar(255)')  ConfigurableFieldValue
          from @XMLData.nodes('//QuoteHeaderXML/QuoteHeaderData/QuoteHeader') as T(X)
         where t.x.value('(Configurable'+cast(@CfgNum as varchar(2))+'/@Value)[1]','varchar(255)') is not null      

        SET @ConfigCounter = @ConfigCounter + 1; 
    END

提前感谢您的帮助、提示和/或想法! =)

【问题讨论】:

  • XML 的.value() 中的部分必须是文字。您的方法适用于动态创建的语句和EXEC,但这是纯粹的程序性思维,没有必要......

标签: sql-server xml


【解决方案1】:

如果此 XML 在您的控制之下,您应该更改它。这是一个非常糟糕的设计,将相同的元素用运行编号作为元素名称的一部分来分隔。如果你需要这个数字,你可以将它添加为属性,如

<Configurable Nr="01" Value="" Name="Credit Memo" />

你不一定需要它,因为元素在 am XML 中的顺序是有保证的(虽然不是属性的顺序),但它使一些查询更容易。

如果您必须坚持这一点,您可以使用星号* 一次性获取&lt;QuoteHeader&gt; 以下的所有节点:

DECLARE @xml XML = 
N'<QuoteHeaderXML>
  <QuoteHeaderData>
    <QuoteHeader>
      <Configurable01 Value="" Name="Credit Memo" />
      <Configurable02 Value="" Name="Contact Person" />
      <Configurable04 Value="N/A" Name="Fed Ex Rated" />
      <Configurable05 Value="Not Branded" Name="Branding" />
      <Configurable06 Value="100%" Name="Project Status" />
      <Configurable07 Value="" Name="Project Name" />
      <Configurable08 Value="None" Name="Project Manager" />
      <Configurable09 Value="" Name="Shipping Notes" />
      <Configurable10 Value="False" Name="High Profile Order" />
      <Configurable11 Value="New Construction" Name="Project Type" />
      <Configurable12 Value="Single-family" Name="Channel" />
      <Configurable13 Value="US - Texas - Northern" Name="Job Location" />
      <Configurable20 Value="Dealer Warehouse" Name="Delivery Destination" />
    </QuoteHeader>
  </QuoteHeaderData>
</QuoteHeaderXML>';

SELECT ConfigurableX.value(N'local-name(.)',N'nvarchar(max)') AS NodeName
      ,ConfigurableX.value(N'@Value',N'nvarchar(max)') AS Value
      ,ConfigurableX.value(N'@Name',N'nvarchar(max)') AS Name
FROM @xml.nodes(N'/QuoteHeaderXML/QuoteHeaderData/QuoteHeader/*') AS GetAllBelowQuoteHeader(ConfigurableX);

结果

+----------------+-----------------------+----------------------+
| NodeName       | Value                 | Name                 |
+----------------+-----------------------+----------------------+
| Configurable01 |                       | Credit Memo          |
+----------------+-----------------------+----------------------+
| Configurable02 |                       | Contact Person       |
+----------------+-----------------------+----------------------+
| Configurable04 | N/A                   | Fed Ex Rated         |
+----------------+-----------------------+----------------------+
| Configurable05 | Not Branded           | Branding             |
+----------------+-----------------------+----------------------+
| Configurable06 | 100%                  | Project Status       |
+----------------+-----------------------+----------------------+
| Configurable07 |                       | Project Name         |
+----------------+-----------------------+----------------------+
| Configurable08 | None                  | Project Manager      |
+----------------+-----------------------+----------------------+
| Configurable09 |                       | Shipping Notes       |
+----------------+-----------------------+----------------------+
| Configurable10 | False                 | High Profile Order   |
+----------------+-----------------------+----------------------+
| Configurable11 | New Construction      | Project Type         |
+----------------+-----------------------+----------------------+
| Configurable12 | Single-family         | Channel              |
+----------------+-----------------------+----------------------+
| Configurable13 | US - Texas - Northern | Job Location         |
+----------------+-----------------------+----------------------+
| Configurable20 | Dealer Warehouse      | Delivery Destination |
+----------------+-----------------------+----------------------+

【讨论】:

  • 不幸的是,XML 设计来自我们应用程序的供应商......而且它并不是唯一糟糕的设计项目。非常感谢,这就像一个冠军。我添加了以下内容,因为实际上除了 Configurables 之外还有其他字段,尽管我只在示例中给出了这些字段,以免混淆。我补充说: WHERE left(ConfigurableX.value(N'local-name(.)',N'nvarchar(max)'),12) = 'Configurable';
  • @AKenn,没关系,但我更愿意将过滤器放在XQuery 中。通过向* 添加谓词来更改.nodes()*[substring(local-name(),1,12)="Configurable"] 这意味着:所有元素,只要其名称的前 12 个字符是“可配置的” 这没什么大不了的使用小集合,但可以在较大的查询中带来相当多的性能。
猜你喜欢
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
相关资源
最近更新 更多