使用 FLWOR 从另一个 table 获取数据

Using FLWOR to get data from another table

我在 SQL Server 2012 中有一个 table 结构如下:

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

Data 列的类型为 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 更新 table 的每一行,以便在 TextReading 名称

之后查看名为 TextReadingId 的新节点

我有一个辅助 table 文本阅读值 stepid 和 textreadingid

StepId                                TextReadingId 
---------------------------------------------------
e36a3450-1c8f-44da-b4d0-58e5bfe2a987    118
4078c1b1-71ea-4578-ba61-d2f6a5126ba1    119
d466a8ee-9214-4b9c-94f9-2117f5dffe93    401

我希望我的 TextReadingId 值来自上面的table

 <Steplist>
          <Step>
            <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
            <Rank>1</Rank>
            <IsComplete>false</IsComplete>
            <TextReadingName>bug-8588_Updated3</TextReadingName>    
          <TextReadingId>118</TextReadingId>   
          </Step>
          <Step>
            <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
            <Rank>2</Rank>
            <TextReadingName>reading1</TextReadingName>
          <TextReadingId>401</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

最简单的方法是重建每个 Step 节点,然后使用 FOR XML

将其聚合备份

在相关子查询中,我们执行以下操作:

  • 使用 .nodes()
  • 分解 Step 个节点
  • StepId 节点值上左联接 StepReading
  • 创建一个包含新 Step 节点的 未命名 列...
  • ... 包含使用 ./* ...
  • 的现有子项的所有子项
  • ...和一个额外的子节点 TextReadingId,其值来自 StepReading
  • 然后使用 FOR XML
  • 聚合备份
UPDATE sl
SET Data = (
    SELECT v.Step.query('
<Step>{./*,
        if (not(./TextReadingId)) then
            <TextReadingId>{sql:column("sr.TextReadingId")}</TextReadingId>
        else ()
        }
</Step>
    ')
    FROM sl.Data.nodes('/Steplist/Step') v(Step)
    LEFT JOIN StepReading sr ON sr.StepId = v.Step.value('(StepId/text())[1]','uniqueidentifier')
    FOR XML PATH(''), ROOT('Steplist'), TYPE
)
FROM tblStepList sl;

SQL Fiddle