zoukankan      html  css  js  c++  java
  • 在父子关系表中获取子孙后代结点数据SQL查询算法

    常见于目录表结构中(树状结构)如项目目录表,根据目录Id获取其属下所有子结点:

    CREATE    PROCEDURE [dbo].[pGetDescendedPhysicalItemCatalogs](
        @PhysicalItemCatalogId int 
    )
    AS
    set nocount on
    
    BEGIN TRY
        IF NOT EXISTS (SELECT * FROM [tempdb].sys.objects WHERE name = '##PhysicalItemCatalog')
            CREATE TABLE ##PhysicalItemCatalog(
                [PhysicalItemCatalogId] [int] ,
                [Name] [nvarchar](50) NOT NULL ,
                [MnemonicCode] [nvarchar](10) NOT NULL ,
                [ParentId] [int] NOT NULL ,
                [IsDeleted] [bit] NOT NULL ,
                [IsValid] [bit] NOT NULL ,
                [PhysicalSpecialtyId] [int] NOT NULL ,
                [Handled] [bit] NOT NULL default 0
            )
    
        INSERT ##PhysicalItemCatalog(PhysicalItemCatalogId, Name, MnemonicCode, ParentId, IsDeleted, IsValid, PhysicalSpecialtyId)
        SELECT PhysicalItemCatalogId, Name, MnemonicCode, ParentId, IsDeleted, IsValid, PhysicalSpecialtyId 
        FROM entity.PhysicalItemCatalog with(nolock) WHERE PhysicalItemCatalogId > -1 AND ParentId = @PhysicalItemCatalogId
        
        DECLARE @catalogId int 
        SELECT TOP 1 @catalogId = PhysicalItemCatalogId FROM ##PhysicalItemCatalog WHERE Handled = 0
        IF @catalogId IS NOT NULL 
        begin
            update ##PhysicalItemCatalog set Handled = 1 where PhysicalItemCatalogId = @catalogId
            exec [dbo].[pGetDescendedPhysicalItemCatalogs] @catalogId
        end
        ELSE
        begin
            SELECT * FROM ##PhysicalItemCatalog
            DROP TABLE ##PhysicalItemCatalog
        end
    END TRY
    BEGIN CATCH
        IF EXISTS (SELECT * FROM [tempdb].sys.objects WHERE name = '##PhysicalItemCatalog')
            DROP TABLE ##PhysicalItemCatalog
    END CATCH
    
    set nocount off

    使用的场景(譬如更新与根目录不一致的字段值):

    CREATE    PROCEDURE [dbo].[pRecalPhysicalItemCatalogsSpecialty]
    AS
    set nocount on
    
    declare @catalogId int
    declare @specialtyId int
    DECLARE @catalog TABLE (
        [PhysicalItemCatalogId] [int] ,
        [Name] [nvarchar](50) NOT NULL ,
        [MnemonicCode] [nvarchar](10) NOT NULL ,
        [ParentId] [int] NOT NULL ,
        [IsDeleted] [bit] NOT NULL ,
        [IsValid] [bit] NOT NULL ,
        [PhysicalSpecialtyId] [int] NOT NULL ,
        [Handled] [bit] NOT NULL default 0
    )
    
    DECLARE my_cursor CURSOR FOR
    select PhysicalItemCatalogId, PhysicalSpecialtyId from entity.PhysicalItemCatalog where parentId = -1
    and PhysicalItemCatalogId in (select ParentId from entity.PhysicalItemCatalog where ParentId > -1)
    OPEN my_cursor;
    FETCH NEXT FROM my_cursor INTO @catalogId, @specialtyId;
    WHILE @@FETCH_STATUS = 0
    BEGIN
        insert into @catalog exec [dbo].[pGetDescendedPhysicalItemCatalogs] @catalogId
    
        UPDATE t
        SET PhysicalSpecialtyId = @specialtyId 
        FROM entity.PhysicalItemCatalog t, @catalog a
        WHERE t.PhysicalItemCatalogId = a.PhysicalItemCatalogId
    
        delete @catalog
    
        FETCH NEXT FROM my_cursor INTO @catalogId, @specialtyId;
    END;
    CLOSE my_cursor;
    DEALLOCATE my_cursor;
    
    set nocount off


    上述可能存在嵌套不能超过32层的错误问题,修改将查询结果保存到临时表中:

    /*
    * TEST SCRIPT:
        declare @catalogId int
        DECLARE my_cursor CURSOR FOR
        select MedicineCatalogId from mmat.MedicineCatalog with(nolock) WHERE MedicineCatalogId > -1 AND ParentCatalogId = -1
    
        OPEN my_cursor;
        FETCH NEXT FROM my_cursor INTO @catalogId;
        WHILE @@FETCH_STATUS = 0
        BEGIN
            exec [dbo].[pGetChildrenMedicineCatalogs] @catalogId
            FETCH NEXT FROM my_cursor INTO @catalogId;
        END;
    
        CLOSE my_cursor;
        DEALLOCATE my_cursor;
        
        IF EXISTS (SELECT * FROM [tempdb].sys.objects WHERE name = '##MedicineCatalog')
        BEGIN
            SELECT * FROM ##MedicineCatalog ORDER BY ParentCatalogId, MedicineCatalogId
            DROP TABLE ##MedicineCatalog
        END
    */
    CREATE    PROCEDURE [dbo].[pGetChildrenMedicineCatalogs](
        @MedicineCatalogId int
    )
    
    AS
    set nocount on
    IF NOT EXISTS (SELECT * FROM [tempdb].sys.objects WHERE name = '##MedicineCatalog')
        CREATE TABLE ##MedicineCatalog(
            [MedicineCatalogId] [int] ,
            [Name] [nvarchar](50) NOT NULL ,
            [SubstanceClassCodeId] [tinyint] NOT NULL ,
            [SpellCode] [nvarchar](20) NULL ,
            [ParentCatalogId] [int] NOT NULL ,
            [IsDeleted] [bit] NOT NULL ,
            [Handled] [bit] NOT NULL default 0
        )
    
    DECLARE @MedicineCatalog TABLE (
        [RID] INT IDENTITY(1,1),
        [MedicineCatalogId] [int] ,
        [Name] [nvarchar](50) NOT NULL ,
        [SubstanceClassCodeId] [tinyint] NOT NULL ,
        [SpellCode] [nvarchar](20) NULL ,
        [ParentCatalogId] [int] NOT NULL ,
        [IsDeleted] [bit] NOT NULL ,
        [Handled] [bit] NOT NULL default 0
    )
     
    INSERT ##MedicineCatalog(MedicineCatalogId, Name, SubstanceClassCodeId, SpellCode, ParentCatalogId, IsDeleted)
    SELECT MedicineCatalogId, Name, SubstanceClassCodeId, SpellCode, ParentCatalogId, IsDeleted 
    FROM mmat.MedicineCatalog with(nolock) WHERE MedicineCatalogId > -1 AND ParentCatalogId = @MedicineCatalogId
    
    declare @count INT
    
    INSERT @MedicineCatalog(MedicineCatalogId, Name, SubstanceClassCodeId, SpellCode, ParentCatalogId, IsDeleted)
    SELECT MedicineCatalogId, Name, SubstanceClassCodeId, SpellCode, ParentCatalogId, IsDeleted 
    FROM mmat.MedicineCatalog with(nolock) WHERE MedicineCatalogId > -1 AND ParentCatalogId = @MedicineCatalogId
    
    SELECT @count = @@ROWCOUNT;
    declare @catalogId INT
    declare @rid INT
    SET @rid = 1;
    WHILE @rid <= @count
    BEGIN
        SELECT @catalogId = MedicineCatalogId FROM @MedicineCatalog mc WHERE RID = @rid;
        update ##MedicineCatalog set Handled = 1 where MedicineCatalogId = @catalogId
        exec [dbo].[pGetChildrenMedicineCatalogs] @catalogId
    
        SET @rid = @rid + 1;
    END
    
    set nocount off
    GO
    
    
    
    
    
    
  • 相关阅读:
    中移动ipv6-老毛子固件获取ipv6设置
    win7-win10 禁用IPV6临时地址
    辅助调用函数【call,apply,bind】
    Unraid修改docker镜像地址&默认启动
    docker基本入门知识-小白向
    [不止于代码]Unraid基本使用速记
    Dockerfile文件说明
    Git之pull,fetch差别
    代码片段添加智能提示,打造一款人见人爱的ORM框架
    新定义三层,指挥官模式
  • 原文地址:https://www.cnblogs.com/chriskwok/p/1621279.html
Copyright © 2011-2022 走看看