0

鉴于以下 XML,所有名为IsEurozone的节点都必须重命名为HasFxrEuro

<?xml version="1.0" encoding="utf-8"?>
<MacroScenarios>
  <MacroScenario>
    <Id>1</Id>
    <Name>Macro Scenario 1</Name>
    <Scenarios>
      <Scenario>
        <CountryIsoAlpha3>USA</CountryIsoAlpha3>
        <Id>1</Id>
        <IsEurozone>true</IsEurozone>
      </Scenario>
      <Scenario>
        <CountryIsoAlpha3>GER</CountryIsoAlpha3>
        <Id>2</Id>
        <IsEurozone>true</IsEurozone>
      </Scenario>
    </Scenarios>
  </MacroScenario>
</MacroScenarios>

替换操作可以轻松完成(感谢 Mikael Erikssons 发布的How to rename XML node name in a SQL Server):

UPDATE [dbo].[MacroScenarioSets] set
[ContentAsXml] = 
        replace(
            replace(
                cast(ContentAsXml as nvarchar(max)), 
                '<IsEurozone>', 
                '<HasFxrEuro>'),
            '</IsEurozone>', 
            '</HasFxrEuro>')

之后,场景节点的内容将如下所示:

  <Scenario>
    <CountryIsoAlpha3>USA</CountryIsoAlpha3>
    <Id>1</Id>
    <HasFxrEuro>true</HasFxrEuro>
  </Scenario>

但就我而言,我需要严格按字母顺序排列节点,因此HasFxrEuro必须放在Id之前。

我的想法是做类似的事情

UPDATE [dbo].[MacroScenarioSets]
SET ContentAsXml.modify('insert 
<HasFxrEuro>{(/MacroScenarios/MacroScenario/Scenarios/Scenario/IsEurozone/text())}</HasFxrEuro>
after (/MacroScenarios/MacroScenario/Scenarios/Scenario/CountryIsoAlpha3)')

然后删除所有旧的IsEurozone节点。但是 XML DML 需要一个用于插入语句的单例。是否有另一种方法可以使用 XML DML 实现这一目标?

4

1 回答 1

0

好的,最后我通过手动浏览 XML 文档来运行它:

    declare @scenarioCursor int = 1
    declare @macroScenarioCursor int = 1

    while 1 = 1
    begin

            -- Add HasFxrEuro with the value of IsEurozone
           UPDATE @myxml
           SET content.modify('
               insert 
                <HasFxrEuro>{(/MacroScenarios/MacroScenario[sql:variable("@macroScenarioCursor")]/Scenarios/Scenario[sql:variable("@scenarioCursor")]/IsEurozone[1]/text())}</HasFxrEuro>
               after ((/MacroScenarios/MacroScenario[sql:variable("@macroScenarioCursor")]/Scenarios/Scenario[sql:variable("@scenarioCursor")]/CountryIsoAlpha3))[1]')
           WHERE content.exist('
                (/MacroScenarioSet/MacroScenarios/MacroScenario[sql:variable("@macroScenarioCursor")]/Scenarios/Scenario[sql:variable("@scenarioCursor")])') = 1

           if @@ROWCOUNT = 0 
           begin
                -- the end
                if @scenarioCursor = 1
                    break;
                else
                    -- increment cursor over MacroScenario, reset cursor over Scenario
                   begin
                         SET @macroScenarioCursor = @macroScenarioCursor + 1
                         SET @scenarioCursor = 1
                   end 
            end       
            else
                begin

                    -- HasFxrEuro has been added remove IsEurozone
                    UPDATE @myxml
                    SET content.modify('
                        delete (/MacroScenarios/MacroScenario[sql:variable("@macroScenarioCursor")]/Scenarios/Scenario[sql:variable("@scenarioCursor")]/IsEurozone)')

                    -- increment Scenario cursor
                    SET @scenarioCursor = @scenarioCursor + 1
               end

end

解决方案非常缓慢。但我不知道如何在 SQL 中解决这个问题。

于 2016-02-24T15:05:00.600 回答