SQL:递归更新表中的 xml 列

Posted

技术标签:

【中文标题】SQL:递归更新表中的 xml 列【英文标题】:SQL: Update xml column in a table recursively 【发布时间】:2021-12-12 01:43:44 【问题描述】:

我在 sql server 2012 中有一个表

具有以下列定义

   CREATE TABLE [dbo].[tblStepList](
    [ToDoId] [int] IDENTITY(1,1) NOT NULL,
    [Data] [xml] NOT NULL

并且数据列是xml与

<Steplist>
  <Step>
    <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
    <Rank>1</Rank>
    <IsComplete>false</IsComplete>
    <TextReadingName>bug-8588_Updated3</TextReadingName>     
  </Step>
  <Step>
    <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
    <Rank>2</Rank>
    <TextReadingName>reading1</TextReadingName>
  </Step>
</Steplist>'

我想用我的新 xml 更新表格的每一行,以便在 TextReading 名称之后使用名为 TextReadingId 的新节点来查看

我想插入一个名为 TextReadingId 的新节点我希望我的 TextReadingId 值是如下的运行数字

 <Steplist>
          <Step>
            <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
            <Rank>1</Rank>
            <IsComplete>false</IsComplete>
            <TextReadingName>bug-8588_Updated3</TextReadingName>    
          <TextReadingId>1</TextReadingId>   
          </Step>
          <Step>
            <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
            <Rank>2</Rank>
            <TextReadingName>reading1</TextReadingName>
          <TextReadingId>1</TextReadingId> 
          </Step>
        </Steplist>';

这是我尝试过的,但没有按预期工作

DECLARE @i int;

SELECT

@i = s.data.value('count(/Steplist/Step)', 'nvarchar(max)')

FROM tblStepList   s

SET data.modify('insert <TextReadingId>sql:variable("@i")</TextReadingId> as last into (/Steplist/Step[sql:variable("@i")])[1]')

print @i
End

【问题讨论】:

&lt;TextReadingId&gt; 元素值只是一个流水号吗? 您使用的是哪个 dbms? 是一个流水号。我正在使用 sql server 提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表和 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。 @YitzhakKhabinsky Khabinsky 我刚刚更新了它 【参考方案1】:

请尝试以下解决方案。

它正在使用 XQuery 及其 FLWOR 表达式。

SQL

USE tempdb;
GO

DROP TABLE IF EXISTS [dbo].[tblStepList];

CREATE TABLE [dbo].[tblStepList](
    [ToDoId] [int] IDENTITY(1,1) NOT NULL,
    [Data] [xml] NOT NULL
);

INSERT INTO dbo.tblStepList ([Data]) VALUES
(N'<Steplist>
  <Step>
    <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
    <Rank>1</Rank>
    <IsComplete>false</IsComplete>
    <TextReadingName>bug-8588_Updated3</TextReadingName>     
  </Step>
  <Step>
    <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
    <Rank>2</Rank>
    <TextReadingName>reading1</TextReadingName>
  </Step>
</Steplist>');

-- before
SELECT * FROM dbo.tblStepList;

UPDATE dbo.tblStepList
SET [Data]  = [Data].query('<Steplist>

    for $x in /Steplist/Step
    let $pos := count(Steplist/*[. << $x]) + 1
    return <Step>$x/*,
        if (not($x/TextReadingId)) then <TextReadingId>$pos</TextReadingId>
        else () 
        </Step>

</Steplist>');

-- after
SELECT * FROM dbo.tblStepList;

【讨论】:

我刚刚更新了我的问题 我可以通过使用 FLWOR 从辅助表中获取值吗?插入流水号 所以你在比赛中途改变了球门柱。我没有看到使用其他表格代替运行数字的简单方法。 我将问题恢复到原来的位置并问了另一个问题***.com/questions/69728769/… @Yitzhak Khabinsky 你能查一下***.com/q/69843694/3038042

以上是关于SQL:递归更新表中的 xml 列的主要内容,如果未能解决你的问题,请参考以下文章

sql将一个表中的某一列数据更新到另一个表中

SQL 从另一个表中的另一列更新一列

SQL Server 删除触发器以更新同一表中的多个列

PL/SQL 使用一张表中的列数据更新表,基于不同表之间的相等性

当没有明确的列可以加入时,如何使用另一个表中的值更新 sql 表?

将新列添加到现有表中并使用 PL/SQL 中游标中的值更新它们