动态更改XML节点名称以循环访问SQL Server中的长列表

时间:2017-12-14 23:33:09

标签: sql-server xml

你们上次帮助很大,我在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,Name和Value提取列,我必须写这个50x以将它们全部拉到它们存在的各个行中......或者为50中的每一行调出每个行最终在150+列表!我不喜欢这些选择。

相反,我希望编写代码以将ConfigurableNN,Name和Value拉一次,但让它根据计数器动态更改节点的数量。但是,我无法做到这一点,因为它抱怨&#34; XML数据类型方法的参数1&#34;值&#34;必须是字符串文字。&#34;。

这是我尝试过的,并且从我发现的帖子中得到了充实但却无法工作......任何建议或者这是不可能的?

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

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

1 个答案:

答案 0 :(得分:2)

如果此XML在您的控制之下,则应更改此值。这是一个非常糟糕的设计,将相同的元素与运行数字分开作为元素名称的一部分。如果您需要此号码,可以将其添加为

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

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

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

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 |
+----------------+-----------------------+----------------------+