Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何通过连接另一个表从数据中更新具有多个相同xml元素的表中的xml_Sql Server_Xml_Tsql_Xquery_Xml.modify - Fatal编程技术网

Sql server 如何通过连接另一个表从数据中更新具有多个相同xml元素的表中的xml

Sql server 如何通过连接另一个表从数据中更新具有多个相同xml元素的表中的xml,sql-server,xml,tsql,xquery,xml.modify,Sql Server,Xml,Tsql,Xquery,Xml.modify,我有一个包含XML列的表。现在,这个XML列有多个类似于数组的标记。每一个标记都有一个属性(),我想通过连接它从表中更新它 表A如下 Id XML 1 "<Root><Object ObjId = "1" Text = "A"><Object Id = "2" Text = "B"></Root>" 2 "<Ro

我有一个包含XML列的表。现在,这个XML列有多个类似于数组的标记。每一个标记都有一个属性(),我想通过连接它从表中更新它

表A如下

Id    XML
1     "<Root><Object ObjId = "1" Text = "A"><Object Id = "2" Text = "B"></Root>"
2     "<Root><Object ObjId = "1" Text = "M"><Object Id = "12" Text = "N"></Root>"
<Root>
   <Object Id = "1" Text = "A">
   <Object Id = "2" Text = "B">
   <Object Id = "3" Text = "C">
   <Object Id = "4" Text = "D">
   <Object Id = "5" Text = "E">
</Root>
我找不到在XML.modify方法中创建动态路径的解决方案。下面是我开始的查询,这可能解释了我正在尝试做什么

UPDATE TblA SET XML.modify(replace value of (/Root/Object) with Table_B.Value)
FROM TABLE_A TblA
CROSS APPLY TblA.XML.nodes('/Root/Object') AS xmlObjs(obj)
INNER JOIN Table_B TblB ON TblB.Table_A_Id = TblA.Id AND TblB.ObjId = xmlObjs.obj.value('@ObjId[1]','varchar(MAX)')

您似乎知道:
.modify()
不允许每次调用进行多个更改。您必须使用
光标
WHILE
循环,以便逐个更新每个事件

因此,我建议采用这种方法:

首先,我们创建模型表来模拟您的问题:

DECLARE @tblA TABLE(Id INT, [XML] XML)
INSERT INTO @tblA VALUES
(1,N'<Root>
       <Object Id = "1" Text = "A"/>
       <Object Id = "2" Text = "B"/>
       <Object Id = "5" Text = "E"/>
   </Root>')
,(2,N'<Root>
       <Object Id = "1" Text = "F"/>
       <Object Id = "2" Text = "G"/>
       <Object Id = "12" Text = "J"/>
       <Object Id = "13" Text = "J"/>
   </Root>')

DECLARE @tblB TABLE(Table_A_Id INT,[ObjId] INT,[Value] VARCHAR(10));
INSERT INTO @tblB VALUES
 (1,1 ,'Q')
,(1,2 ,'R')
,(2,1 ,'S')
,(2,12,'T');
--检查结果

SELECT * FROM @tblA;
简而言之:

  • 我们使用可更新的CTE将表A的数据读入列表
  • 我们使用相关子查询动态创建修改后的XML
  • 我们在现有XML的基础上编写新的XML
更新

下次请尽量避免一个变色龙问题。。。你的评论让这一切变得完全不同。。。下次请关闭一个问题,如果它是按原样回答,并开始一个新的问题,以防你发现,你最初的问题并没有真正涵盖你的需要

试试这个:

DECLARE @tblA TABLE(Id INT, [XML] XML)
INSERT INTO @tblA VALUES
(1,N'<Root> 
       <AnotherTag val="abc"/> 
       <AnotherTag val="DEF"/> 
       <Object Id =  "1" Text = "F" OtherProperty = "123" /> 
       <Object Id =  "2" Text = "G" SampleProperty = "Anything" DataProperty="Sample Data" /> 
       <Object Id = "12" Text = "I" OtherProperty = "123"/> 
       <Object Id = "13" Text = "J" DataProperty = "Sample"/> 
     </Root>')
,(2,N'<Root>
       <Object Id = "1" Text = "F"/>
       <Object Id = "2" Text = "G"/>
       <Object Id = "12" Text = "I"/>
       <Object Id = "13" Text = "J"/>
   </Root>')

DECLARE @tblB TABLE(Table_A_Id INT,[ObjId] INT,[Value] VARCHAR(10));
INSERT INTO @tblB VALUES
 (1,1 ,'Q')
,(1,2 ,'R')
,(2,1 ,'S')
,(2,12,'T');

WITH cte AS
(
    SELECT ta.Id
          ,ta.[XML]
          ,Combined.[CombXml].query('<Root>
                                     {
                                        for $elmt in /combined/embedded/Root/*
                                        let $bVal := /combined/b_data[ObjId[1] = $elmt/@Id]/Value/text()
                                        return
                                        if(local-name($elmt) eq "Object") then 
                                            <Object Id="{$elmt/@Id}" Text="{if(empty($bVal)) then $elmt/@Text else $bVal}">
                                            {$elmt/@*[local-name() != "Id" and local-name() != "Text"]}
                                            </Object>
                                        else
                                            $elmt
                                     }
                                     </Root>') AS NewXml
    FROM @tblA ta
    OUTER APPLY(SELECT (SELECT [ObjId],[Value] 
                        FROM @tblB tb 
                        WHERE tb.Table_A_Id=ta.Id 
                        FOR XML PATH('b_data'),TYPE) AS [*]
                       ,ta.[XML] AS [embedded]
                       FOR XML PATH(''),ROOT('combined'),TYPE) Combined([CombXml])
)
UPDATE cte SET [XML] = NewXml;

SELECT * FROM @tblA;
针对这个组合的XML,我们可以使用
.query()
运行FLWOR查询

  • 此查询将通过以下所有节点运行
  • 您端数据的相应
    (在XML its
    中)被分配给
    $bVal
  • 现在我们检查当前元素的名称是否为
  • 如果是这样,我们直接编写属性
    Id
    Text
    ,并添加所有其他属性,而不查看它们
  • 如果没有,我们就按原样退回$elmt
Id=1的结果如下所示:

<Root>
  <AnotherTag val="abc" />
  <AnotherTag val="DEF" />
  <Object Id="1" Text="Q" OtherProperty="123" />
  <Object Id="2" Text="R" SampleProperty="Anything" DataProperty="Sample Data" />
  <Object Id="12" Text="I" OtherProperty="123" />
  <Object Id="13" Text="J" DataProperty="Sample" />
</Root>

您可以看到,“Q”和“R”在Id为1或2时发生了变化-根据侧数据

我必须承认,事情变得复杂了


根据您的实际数据和XML的复杂性,使用
.modify()
的循环方法可能更好…

很好的答案,+1来自我这边!嗨,Shnugo,谢谢你的回复。在实际场景中,我在XML中有一点不同。我希望你也能在这方面帮助我。”XML中的某些对象标记具有其他属性。但并不是所有人都具有这些特性。请帮忙
DECLARE @tblA TABLE(Id INT, [XML] XML)
INSERT INTO @tblA VALUES
(1,N'<Root> 
       <AnotherTag val="abc"/> 
       <AnotherTag val="DEF"/> 
       <Object Id =  "1" Text = "F" OtherProperty = "123" /> 
       <Object Id =  "2" Text = "G" SampleProperty = "Anything" DataProperty="Sample Data" /> 
       <Object Id = "12" Text = "I" OtherProperty = "123"/> 
       <Object Id = "13" Text = "J" DataProperty = "Sample"/> 
     </Root>')
,(2,N'<Root>
       <Object Id = "1" Text = "F"/>
       <Object Id = "2" Text = "G"/>
       <Object Id = "12" Text = "I"/>
       <Object Id = "13" Text = "J"/>
   </Root>')

DECLARE @tblB TABLE(Table_A_Id INT,[ObjId] INT,[Value] VARCHAR(10));
INSERT INTO @tblB VALUES
 (1,1 ,'Q')
,(1,2 ,'R')
,(2,1 ,'S')
,(2,12,'T');

WITH cte AS
(
    SELECT ta.Id
          ,ta.[XML]
          ,Combined.[CombXml].query('<Root>
                                     {
                                        for $elmt in /combined/embedded/Root/*
                                        let $bVal := /combined/b_data[ObjId[1] = $elmt/@Id]/Value/text()
                                        return
                                        if(local-name($elmt) eq "Object") then 
                                            <Object Id="{$elmt/@Id}" Text="{if(empty($bVal)) then $elmt/@Text else $bVal}">
                                            {$elmt/@*[local-name() != "Id" and local-name() != "Text"]}
                                            </Object>
                                        else
                                            $elmt
                                     }
                                     </Root>') AS NewXml
    FROM @tblA ta
    OUTER APPLY(SELECT (SELECT [ObjId],[Value] 
                        FROM @tblB tb 
                        WHERE tb.Table_A_Id=ta.Id 
                        FOR XML PATH('b_data'),TYPE) AS [*]
                       ,ta.[XML] AS [embedded]
                       FOR XML PATH(''),ROOT('combined'),TYPE) Combined([CombXml])
)
UPDATE cte SET [XML] = NewXml;

SELECT * FROM @tblA;
<combined>
  <b_data>
    <ObjId>1</ObjId>
    <Value>Q</Value>
  </b_data>
  <b_data>
    <ObjId>2</ObjId>
    <Value>R</Value>
  </b_data>
  <embedded>
    <Root>
      <AnotherTag val="abc" />
      <AnotherTag val="DEF" />
      <Object Id="1" Text="F" OtherProperty="123" />
      <Object Id="2" Text="G" SampleProperty="Anything" DataProperty="Sample Data" />
      <Object Id="12" Text="J" OtherProperty="123" />
      <Object Id="13" Text="J" DataProperty="Sample" />
    </Root>
  </embedded>
</combined>
<Root>
  <AnotherTag val="abc" />
  <AnotherTag val="DEF" />
  <Object Id="1" Text="Q" OtherProperty="123" />
  <Object Id="2" Text="R" SampleProperty="Anything" DataProperty="Sample Data" />
  <Object Id="12" Text="I" OtherProperty="123" />
  <Object Id="13" Text="J" DataProperty="Sample" />
</Root>