XML树结构,修改

问题描述 投票:0回答:1

我在 SQL Server 中有一个表示层次结构数据的 XML 结构,我需要根据每个项目在层次结构中的位置来更新每个项目的 ItemNumber。这是我到目前为止所拥有的:

DECLARE @ItemsXml XML = 
    (
        SELECT  dbo.GetCurrentLanguageValue(ti.Title, @Language) AS 'EntityTitle',
                ti.[Order] AS 'ItemNumber',
                ti.ParentId as 'ParentId',
                ti.Id as 'Id',
                m.RegistrationNumber as 'RegistrationNumber',
                CONVERT(NVARCHAR, m.RegistrationDate, 4) AS 'RegistrationDate',
                dbo.GetCurrentLanguageValue(s.Title, @Language) AS 'EntityState',
                dbo.GetCurrentLanguageValue(mt.Title, @Language) AS 'MaterialTypeTitle',
                IIF(m.ProposerMPId is not null, 
                    dbo.GetCurrentLanguageValue(u.FirstName, @Language) + ' ' + dbo.GetCurrentLanguageValue(u.LastName, @Language), 
                    dbo.GetCurrentLanguageValue(m.ResponsibleProposer, @Language)) AS 'EntityProposer',
                dbo.AgendaSittingAtachments(ti.Id, @Language) AS 'AgendaSittingAttachment'
        FROM TreeItems AS ti
        INNER JOIN CategorizationLinks cl ON cl.CategorizationId = ti.CategorizationId
        LEFT OUTER JOIN TreeItemValues tiv ON tiv.TreeItemId = ti.Id
        LEFT OUTER JOIN Materials m ON m.Id = tiv.MaterialId
        LEFT OUTER JOIN MaterialTypes mt on mt.Id = m.[Type]
        LEFT OUTER JOIN Statuses s ON s.Id = m.[Status]
        LEFT OUTER JOIN Users u ON u.Id = m.ProposerMPId
        LEFT OUTER JOIN TreeItems tiParent ON tiParent.Id = ti.ParentId
        WHERE cl.SittingId = @ObjectId AND (m.[Type] IS NULL OR m.[Type] not in (24, 51, 57, 58))
        AND (ti.EmptyItemTypeId is null or tiParent.TreeItemTypeId <> 3) AND ti.ParentId is not null
        ORDER BY ti.[Order]
        FOR XML PATH ('Items')
    )
<Items>
  <EntityTitle>Receive and File a Report from Community Action of the County on the 2023-2024 Community Needs Assessment and Community Action Plan</EntityTitle>
  <ItemNumber>1</ItemNumber>
  <ParentId>E9BBEF90-0915-41F3-87D0-AAD943C0554F</ParentId>
  <Id>BC94E6D1-B8D8-44CE-A7CB-963A048FFCAF</Id>
  <EntityState>Business committee consideration</EntityState>
  <MaterialTypeTitle>Motion for adoption of the report</MaterialTypeTitle>
  <EntityProposer>Epar User1</EntityProposer>
</Items>
<Items>
  <EntityTitle>cat2</EntityTitle>
  <ItemNumber>1</ItemNumber>
  <ParentId>AD4F8BB1-0FE4-4078-BF34-9B509B20A723</ParentId>
  <Id>558CD287-BB26-4A76-9388-BC98CC486B30</Id>
</Items>
<Items>
  <EntityTitle>cat1</EntityTitle>
  <ItemNumber>2</ItemNumber>
  <ParentId>E9BBEF90-0915-41F3-87D0-AAD943C0554F</ParentId>
  <Id>B0B88E8A-CEAB-4023-9E1C-5F202131D146</Id>
</Items>
<Items>
  <EntityTitle>Annual appro #1</EntityTitle>
  <ItemNumber>2</ItemNumber>
  <ParentId>B0B88E8A-CEAB-4023-9E1C-5F202131D146</ParentId>
  <Id>E0B7B388-FB1B-4293-BA80-9FFD161732B2</Id>
  <EntityState>Committee consideration I reading</EntityState>
  <MaterialTypeTitle>Annual Appropriation Bill </MaterialTypeTitle>
  <EntityProposer>Epar User1</EntityProposer>
</Items>
<Items>
  <EntityTitle>Test Kiko Redirect</EntityTitle>
  <ItemNumber>2</ItemNumber>
  <ParentId>B0B88E8A-CEAB-4023-9E1C-5F202131D146</ParentId>
  <Id>AD4F8BB1-0FE4-4078-BF34-9B509B20A723</Id>
  <EntityState>Committee consideration I reading</EntityState>
  <MaterialTypeTitle>Annual Appropriation Bill </MaterialTypeTitle>
  <EntityProposer>epar_user15 test15</EntityProposer>
</Items>
<Items>
  <EntityTitle>Annual Appropriation Bill</EntityTitle>
  <ItemNumber>3</ItemNumber>
  <ParentId>B0B88E8A-CEAB-4023-9E1C-5F202131D146</ParentId>
  <Id>F551FB03-2794-4209-9C29-88C2862CCE57</Id>
  <EntityState>Committee consideration I reading</EntityState>
  <MaterialTypeTitle>Annual Appropriation Bill </MaterialTypeTitle>
  <EntityProposer>Simona Radinska Andovski</EntityProposer>
</Items>

目标是更新 ItemNumber 字段,以便根据项目的层次结构级别对项目进行编号。例如,如果某个项目的父级为 1,则其 ItemNumber 应为 1.1、1.2 等。

我尝试直接在 UPDATE 语句中使用窗口函数,但遇到了限制。

有人可以建议一种替代方法来根据 XML 数据的层次结构有效更新 ItemNumber 字段吗?

谢谢!

sql sql-server xml t-sql tree
1个回答
0
投票

您可以使用递归 CTE 来构建项目编号。然后将其他所有内容加入其中。

  • 您不能在
    WITH
    DECLARE
    上使用
    SET
    ,您需要一个
    SELECT
  • 您需要将第一行转换为
    nvarchar(4000)
    nvarchar(max)
    否则您将收到类型绑定错误。
  • 请勿使用没有长度的
    n/varchar
  • 如果要将其存储为
    , TYPE
    类型,请在
    FOR XML
    上使用
    xml
  • 谓词
    tiParent.TreeItemTypeId <> 3
    似乎只指直接父级,而不是树的顶部。如果要求不同,那么您需要更改 CTE。
  • 我不知道
    dbo.GetCurrentLanguageValue
    的作用,但它可能会被分解为内联表值函数,这通常更快。
DECLARE @ItemsXml XML;

WITH cte AS (
    SELECT
        ti.[Order],
        ti.ParentId,
        ti.Id as Id,
        ti.EmptyItemTypeId,
        ti.TreeItemTypeId,
        NULL AS ParentTreeItemTypeId,
        CAST(ti.[Order] AS nvarchar(4000)) AS ItemNumber
    FROM TreeItems ti
    WHERE ti.ParentId IS NULL

    UNION ALL

    SELECT
        ti.[Order],
        ti.ParentId,
        ti.Id as Id,
        ti.EmptyItemTypeId,
        ti.TreeItemTypeId,
        cte.TreeItemTypeId,
        CONCAT(cte.ItemNumber, N'.', ti.[Order])
    FROM TreeItems ti
    JOIN cte tiParent ON tiParent.Id = ti.ParentId
)
SELECT @ItemsXml = 
    (
        SELECT
            dbo.GetCurrentLanguageValue(ti.Title, @Language) AS EntityTitle,
            ti.ItemNumber,
            ti.ParentId,
            ti.Id,
            m.RegistrationNumber,
            CONVERT(NVARCHAR(30), m.RegistrationDate, 4) AS RegistrationDate,
            dbo.GetCurrentLanguageValue(s.Title, @Language) AS EntityState,
            dbo.GetCurrentLanguageValue(mt.Title, @Language) AS MaterialTypeTitle,
            IIF(m.ProposerMPId is not null, 
                dbo.GetCurrentLanguageValue(u.FirstName, @Language) + ' ' + dbo.GetCurrentLanguageValue(u.LastName, @Language), 
                dbo.GetCurrentLanguageValue(m.ResponsibleProposer, @Language)) AS EntityProposer,
            dbo.AgendaSittingAtachments(ti.Id, @Language) AS AgendaSittingAttachment
        FROM cte AS ti
        INNER JOIN CategorizationLinks cl ON cl.CategorizationId = ti.CategorizationId
        LEFT OUTER JOIN TreeItemValues tiv ON tiv.TreeItemId = ti.Id
        LEFT OUTER JOIN Materials m ON m.Id = tiv.MaterialId
        LEFT OUTER JOIN MaterialTypes mt on mt.Id = m.[Type]
        LEFT OUTER JOIN Statuses s ON s.Id = m.Status
        LEFT OUTER JOIN Users u ON u.Id = m.ProposerMPId
        LEFT OUTER JOIN TreeItems tiParent ON tiParent.Id = ti.ParentId
        WHERE cl.SittingId = @ObjectId
          AND (m.[Type] IS NULL OR m.[Type] not in (24, 51, 57, 58))
          AND (ti.EmptyItemTypeId is null or ti.ParentTreeItemTypeId <> 3)
          AND ti.ParentId is not null
        ORDER BY ti.[Order]
        FOR XML PATH ('Items'), TYPE
    );
© www.soinside.com 2019 - 2024. All rights reserved.