移动 XML 中的节点并使用 XML DML 重命名它们
Moving nodes in XML and rename them using XML DML
鉴于以下 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 post 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.[=17 之前=]
我的想法是做类似
的事情
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 来实现?
好吧,通过手动浏览 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.
中解决这个问题
鉴于以下 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 post 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.[=17 之前=]
我的想法是做类似
的事情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 来实现?
好吧,通过手动浏览 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.
中解决这个问题