【问题标题】:Copy a bulk of sub nodes to existing node将大量子节点复制到现有节点
【发布时间】:2020-09-09 10:06:03
【问题描述】:

我正在尝试:

  1. 遍历包含 XML [MY_TABLE 中的MY_XML_COLUMN] 的列
  2. 对于每个 XML:
    1. 获取某种类型的所有节点 ([@type="myType"])
    2. 对于每个“myType”节点:
      1. 检查它是否包含一个子节点“myEvent”(注意 - 如果存在 - 只有一个)
      2. 如果是这样:
        1. 将所有值从该节点复制(更新)到另一个具有相同子节点的“myNewEvent”节点 像“myEvent”这样的节点
        2. 无论如何从所有“myType”节点中删除“myEvent”节点

例子:

<hubs>
  <hubOne type="myType">   (myNewEvent should b updated as its of "myType" hub and has "myEvent" node)
     <myEvent>
       <subNodeOne> x <subNodeOne>
       <subNodeTwo> y <subNodeTwo>
       <subNodeThree> z <subNodeThree>
     </myEvent>
     <myNewEvent>
       <subNodeOne> a <subNodeOne>
       <subNodeTwo> b <subNodeTwo>
       <subNodeThree> c <subNodeThree>
     </myNewEvent> 
  </hubOne>
  <hubTwo type="NOTmyType"> (myNewEvent should NOT b updated as its NOT of "myType" hub)
     <myEvent>
       <subNodeOne> x <subNodeOne>
       <subNodeTwo> y <subNodeTwo>
       <subNodeThree> z <subNodeThree>
     </myEvent>
     <myNewEvent>
       <subNodeOne> a <subNodeOne>
       <subNodeTwo> b <subNodeTwo>
       <subNodeThree> c <subNodeThree>
     </myNewEvent> 
  </hubTwo>
  <hubThree type="myType"> (myNewEvent should NOT b updated as its of "myType" but no subnode "myEvent")
     <myNewEvent>
       <subNodeOne> x <subNodeOne>
       <subNodeTwo> y <subNodeTwo>
       <subNodeThree> z <subNodeThree>
     </myNewEvent>
  </hubThree>
  <hubFour type="myType"> (myNewEvent should b updated as its of "myType" hub and has "myEvent" node)
     <myEvent>
       <subNodeOne> q <subNodeOne>
       <subNodeTwo> w <subNodeTwo>
       <subNodeThree> e <subNodeThree>
     </myEvent>
     <myNewEvent>
       <subNodeOne> a <subNodeOne>
       <subNodeTwo> b <subNodeTwo>
       <subNodeThree> c <subNodeThree>
     </myNewEvent> 
  </hubFour>
</hubs>

想要的结果:

<hubs>
  <hubOne type="myType"> (myNewEvent updated and myEvent deleted)
     <myNewEvent>
       <subNodeOne> x <subNodeOne>
       <subNodeTwo> y <subNodeTwo>
       <subNodeThree> z <subNodeThree>
     </myNewEvent> 
  </hubOne>
  <hubTwo type="NOTmyType"> (myNewEvent NOT updated and myEvent deleted)
     <myNewEvent>
       <subNodeOne> a <subNodeOne>
       <subNodeTwo> b <subNodeTwo>
       <subNodeThree> c <subNodeThree>
     </myNewEvent> 
  </hubTwo>
  <hubThree type="myType"> (myNewEvent NOT updated)
     <myNewEvent>
       <subNodeOne> x <subNodeOne>
       <subNodeTwo> y <subNodeTwo>
       <subNodeThree> z <subNodeThree>
     </myNewEvent>
  </hubThree>
  <hubFour type="myType"> (myNewEvent updated and myEvent deleted)
     <myNewEvent>
       <subNodeOne> q <subNodeOne>
       <subNodeTwo> w <subNodeTwo>
       <subNodeThree> e <subNodeThree>
     </myNewEvent> 
  </hubFour>
</hubs>

到目前为止我尝试过的都没有成功:

  1. google + 旧的堆栈溢出解决方案

  2. 代码示例:

DECLARE @ID INT;
DECLARE @HUB_ID UNIQUEIDENTIFIER;
DECLARE @NAME VARCHAR(MAX);

DECLARE PROFILES_CURSOR CURSOR
FOR
SELECT P.[ID] FROM [MY_TABLE] P WHERE P.DELETED=0;
OPEN SOME_CURSOR
FETCH NEXT FROM SOME_CURSOR INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN

DECLARE HUBS_CURSOR CURSOR
FOR
SELECT H.hub.value('(@name)', 'varchar(1024)') AS [NAME]
FROM MY_TABLE
CROSS APPLY MY_XML_COLUMN.nodes('/integration/hub[@type="myType"]') as H(hub)
WHERE PROFILE_ID=@ID
OPEN HUBS_CURSOR
FETCH NEXT FROM HUBS_CURSOR INTO @NAME
WHILE @@FETCH_STATUS = 0
BEGIN

UPDATE [MY_TABLE]
SET [INTEGRATION_XML].modify(some xquery code to deal all nodes at once?)
WHERE ANOTHER_COLUMN = @ID
AND (
SELECT [SOME_IDENTIFYING_COLUMN]
FROM MY_TABLE PS
WHERE PS.MY_XML_COLUMN.exist('/integration/hub[@name=sql:variable("@NAME" and @type="myType")]/events') = 1
AND PS.INTEGRATION_XML.exist('/integration/hub[@name=sql:variable("@NAME" and @type="myType")]/events/myEvent') = 1
AND PROFILE_ID=@ID
) IS NOT NULL
FETCH NEXT FROM HUBS_CURSOR INTO @NAME
END

CLOSE HUBS_CURSOR
DEALLOCATE HUBS_CURSOR
FETCH NEXT FROM PROFILES_CURSOR INTO @ID
END

CLOSE PROFILES_CURSOR
DEALLOCATE PROFILES_CURSOR

【问题讨论】:

  • (1) XML 似乎是手工制作的。它应该是格式良好的。 (2)&lt;hubOne&gt;&lt;hubTwo&gt;等XML元素命名的原因是什么?这是一个非常糟糕的命名约定。
  • @YitzhakKhabinsky 没错。它是手工制作和命名的,以避免泄露业务细节

标签: sql-server xml sql-server-2016


【解决方案1】:

...毁灭?

(在集线器末端创建newEventNode,然后删除myEvent&除最后一个之外的所有newEventNode)

declare @x xml = N'<hubs>
  <hubOne type="myType">   (myNewEvent should b updated as its of "myType" hub and has "myEvent" node)
     <myEvent>
       <subNodeOne> hubone-upd1 </subNodeOne>
       <subNodeTwo> hubone-upd2 </subNodeTwo>
       <subNodeThree> hubone-upd3</subNodeThree>
     </myEvent>
     <myNewEvent>
       <subNodeOne> a </subNodeOne>
       <subNodeTwo> b </subNodeTwo>
       <subNodeThree> c </subNodeThree>
     </myNewEvent> 
  </hubOne>
  <hubTwo type="NOTmyType"> (myNewEvent should NOT b updated as its NOT of "myType" hub)
     <myEvent>
       <subNodeOne> x </subNodeOne>
       <subNodeTwo> y </subNodeTwo>
       <subNodeThree> z </subNodeThree>
     </myEvent>
     <myNewEvent>
       <subNodeOne> a </subNodeOne>
       <subNodeTwo> b </subNodeTwo>
       <subNodeThree> c </subNodeThree>
     </myNewEvent> 
  </hubTwo>
  <hubThree type="myType"> (myNewEvent should NOT b updated as its of "myType" but no subnode "myEvent")
     <myNewEvent>
       <subNodeOne> x </subNodeOne>
       <subNodeTwo> y </subNodeTwo>
       <subNodeThree> z </subNodeThree>
     </myNewEvent>
  </hubThree>
  <hubFour type="myType"> (myNewEvent should b updated as its of "myType" hub and has "myEvent" node)
     <myEvent>
       <subNodeOne> q </subNodeOne>
       <subNodeTwo> hubfour-w </subNodeTwo>
       <subNodeThree> e </subNodeThree>
     </myEvent>
     <myNewEvent>
       <subNodeOne> 1 </subNodeOne>
       <subNodeTwo> 2 </subNodeTwo>
       <subNodeThree> 3 </subNodeThree>
     </myNewEvent> 
  </hubFour>
  
  
  <hubFive type="myType"> (myEvent but there is not myNewEvent....it will be created ??)
     <myEvent>
       <subNodeOne> myNewEvent did not exist </subNodeOne>
       <subNodeTwo> but it was created... </subNodeTwo>
       <subNodeThree> ....?? </subNodeThree>
     </myEvent>
  </hubFive>  
</hubs>';

declare @t table(id int identity, thexml xml);
insert into @t(thexml)
select top (10) @x
from sys.all_objects;

declare @snet smallint = 20 /*max(xquery(count()path to be updated)) from @t*/;
while exists
(
select *
from @t
where thexml.exist('/hubs/*[@type="myType"][./myEvent][count(./myNewEvent) <= 1]') = 1
)
and @snet >= 0
begin
    update @t
    set thexml.modify
    (
    '
    (: add myEvent as last myNewEvent into the parent:)
    insert <myNewEvent>{/hubs/*[@type="myType"][./myEvent][count(./myNewEvent) <= 1][1]/myEvent[1]/*}</myNewEvent>      
    as last         
    into (/hubs/*[@type="myType"][./myEvent][count(./myNewEvent) <= 1])[1]    
    '
    )
    where thexml.exist('/hubs/*[@type="myType"][./myEvent][count(./myNewEvent) <= 1]') = 1

    set @snet = @snet - 1;
end

update @t
set thexml.modify('
(: delete myEvent&myNewEvent nodes except the last one, which was added earlier :)
delete /hubs/*[@type="myType"][./myEvent][count(./myNewEvent) > 1]/*[local-name(.) = ("myEvent", "myNewEvent")][position() < last()]
')

select *
from @t;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2013-12-08
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多