You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL游标优化需求:满足条件时直接跳转至下一行

解决方案:实现游标条件短路检查

你的核心需求是只要某一列对应的关联表状态为0,就更新当前行并直接跳至下一行,不再检查后续列,当前代码的问题是会遍历所有检查逻辑,无法实现短路。可以通过两种方式实现需求:

方法一:IF...ELSE IF 链式检查(推荐)

这种方式天然支持短路逻辑,前面的条件满足时,后续分支不会执行:

Declare @InputResourceId int,@ResourceTypeId int,@CoreAppId int,@SiteId int,@CompetencyID int,@EstaffId int,
@CostCenterId int, @PVLocationId int,@EngineeringCostId int, @CostCategoryId int, @ExpenseTypeId int

Declare InputResourceCursor CURSOR FOR
SELECT InputResourceId, ResourceTypeId,CoreAppId, SiteId, CompetencyId, EStaffId, CostCenterId, PVLocationId
from InputResource where EFITID = 214

OPEN InputResourceCursor

FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId

WHILE (@@FETCH_STATUS = 0)
BEGIN
    Declare @Status1 int
    
    -- 检查第一个表,满足则更新并跳过后续检查
    SET @Status1 = (Select Status from tblResourceType where ResourceTypeId = @ResourceTypeId)
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
    END
    ELSE
    BEGIN
        -- 第一个不满足,检查第二个
        SET @Status1 = (Select Status from tblCoreApp where CoreAppId = @CoreAppId) 
        IF(@Status1 = 0)
        BEGIN
            UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        END
        ELSE
        BEGIN
            -- 第二个不满足,检查第三个
            SET @Status1 = (Select Status from tblSiteMaster where SiteId = @SiteId)    
            IF(@Status1 = 0)
            BEGIN
                UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
            END
            ELSE
            BEGIN
                -- 第三个不满足,检查第四个
                SET @Status1 = (Select Status from tblCompetency where CompetencyId = @CompetencyID)    
                IF(@Status1 = 0)
                BEGIN
                    UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
                END
                ELSE
                BEGIN
                    -- 第四个不满足,检查第五个
                    SET @Status1 = (Select Status from Estaff where EStaffId = @EstaffId)   
                    IF(@Status1 = 0)
                    BEGIN
                        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
                    END
                    ELSE
                    BEGIN
                        -- 第五个不满足,检查第六个
                        SET @Status1 = (Select Status from CostCenter where CostCenterId = @CostCenterId)   
                        IF(@Status1 = 0)
                        BEGIN
                            UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
                        END
                        ELSE
                        BEGIN
                            -- 第六个不满足,检查第七个
                            SET @Status1 = (Select Status from PlanViewLocationMaster where PlanviewLocationID = @PVLocationId) 
                            IF(@Status1 = 0)
                            BEGIN
                                UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
                            END
                        END
                    END
                END
            END
        END
    END

    -- 移动到下一行
    FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
END

CLOSE InputResourceCursor
DEALLOCATE InputResourceCursor

方法二:使用CONTINUE跳过剩余逻辑

如果不想嵌套太多ELSE,可以在每个满足条件的分支中执行更新后,直接执行FETCH NEXT并通过CONTINUE回到循环开头,避免死循环:

Declare @InputResourceId int,@ResourceTypeId int,@CoreAppId int,@SiteId int,@CompetencyID int,@EstaffId int,
@CostCenterId int, @PVLocationId int,@EngineeringCostId int, @CostCategoryId int, @ExpenseTypeId int

Declare InputResourceCursor CURSOR FOR
SELECT InputResourceId, ResourceTypeId,CoreAppId, SiteId, CompetencyId, EStaffId, CostCenterId, PVLocationId
from InputResource where EFITID = 214

OPEN InputResourceCursor

FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId

WHILE (@@FETCH_STATUS = 0)
BEGIN
    Declare @Status1 int
    
    SET @Status1 = (Select Status from tblResourceType where ResourceTypeId = @ResourceTypeId)
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        -- 移动到下一行并跳过剩余逻辑
        FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
        CONTINUE
    END

    SET @Status1 = (Select Status from tblCoreApp where CoreAppId = @CoreAppId) 
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
        CONTINUE
    END

    SET @Status1 = (Select Status from tblSiteMaster where SiteId = @SiteId)    
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
        CONTINUE
    END

    SET @Status1 = (Select Status from tblCompetency where CompetencyId = @CompetencyID)    
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
        CONTINUE
    END

    SET @Status1 = (Select Status from Estaff where EStaffId = @EstaffId)   
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
        CONTINUE
    END

    SET @Status1 = (Select Status from CostCenter where CostCenterId = @CostCenterId)   
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
        CONTINUE
    END

    SET @Status1 = (Select Status from PlanViewLocationMaster where PlanviewLocationID = @PVLocationId) 
    IF(@Status1 = 0)
    BEGIN
        UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
    END

    -- 所有条件都不满足时,移动到下一行
    FETCH NEXT FROM InputResourceCursor INTO @InputResourceId,@ResourceTypeId,@CoreAppId,@SiteId,@CompetencyID,@EstaffId,@CostCenterId,@PVLocationId
END

CLOSE InputResourceCursor
DEALLOCATE InputResourceCursor

额外优化建议

游标在SQL中性能通常较差,如果数据量较大,建议改用集合式更新替代游标,代码更简洁且执行效率更高:

UPDATE ir
SET Status = 2
FROM InputResource ir
WHERE EFITID = 214
AND (
    EXISTS (SELECT 1 FROM tblResourceType rt WHERE rt.ResourceTypeId = ir.ResourceTypeId AND rt.Status = 0)
    OR EXISTS (SELECT 1 FROM tblCoreApp ca WHERE ca.CoreAppId = ir.CoreAppId AND ca.Status = 0)
    OR EXISTS (SELECT 1 FROM tblSiteMaster sm WHERE sm.SiteId = ir.SiteId AND sm.Status = 0)
    OR EXISTS (SELECT 1 FROM tblCompetency c WHERE c.CompetencyId = ir.CompetencyId AND c.Status = 0)
    OR EXISTS (SELECT 1 FROM Estaff e WHERE e.EStaffId = ir.EStaffId AND e.Status = 0)
    OR EXISTS (SELECT 1 FROM CostCenter cc WHERE cc.CostCenterId = ir.CostCenterId AND cc.Status = 0)
    OR EXISTS (SELECT 1 FROM PlanViewLocationMaster plm WHERE plm.PlanviewLocationID = ir.PVLocationId AND plm.Status = 0)
)

内容的提问来源于stack exchange,提问作者Obraine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:25:20