条件满足时移动光标到下一行

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

DI 编写了一个游标来迭代表的行。我的要求是我不想检查所有列的状况。如果我的条件与第 1 列匹配,则不检查其他列的条件并将光标移动到下一行。如果条件与第 1 列不匹配,则检查第 2 列,依此类推。我尝试过使用 Break 和 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
-- Here I want to move my cursor to the next row. If I put my Fetch next here then also its not working properly.
        END

    SET @Status1 = (Select Status from tblCoreApp where CoreAppId = @CoreAppId) 
    IF(@Status1 = 0)
        BEGIN
            UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        END

    SET @Status1 = (Select Status from tblSiteMaster where SiteId = @SiteId)    
    IF(@Status1 = 0)
        BEGIN
            UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        END

    SET @Status1 = (Select Status from tblCompetency where CompetencyId = @CompetencyID)    
    IF(@Status1 = 0)
        BEGIN
            UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        END

    SET @Status1 = (Select Status from Estaff where EStaffId = @EstaffId)   
    IF(@Status1 = 0)
        BEGIN
            UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        END

    SET @Status1 = (Select Status from CostCenter where CostCenterId = @CostCenterId)   
    IF(@Status1 = 0)
        BEGIN
            UPDATE InputResource SET Status = 2 where InputResourceId = @InputResourceId
        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-server t-sql cursor
1个回答
0
投票

我相信您可以在单个

EXISTS(SELECT TOP 1 * FROM (select1 UNION select2 UNION ...) U)
条件内移动所有状态选择,其中每个
selectN
的形式为
Select Status from ... where ... and Status = 0
。我希望 TOP 1 应该快捷方式 UNION ALL,这样一旦找到满足其条件的选择,其余的选择将被跳过。

这种方法可以封装成一个集合操作,从而消除游标循环。

UPDATE I
SET Status = 2
FROM InputResource I
WHERE I.EFITID = 214
AND EXISTS (
    SELECT TOP 1 *
    FROM (
        Select Status from tblResourceType where ResourceTypeId = @ResourceTypeId And Status = 0
        UNION ALL
        Select Status from tblCoreApp where CoreAppId = @CoreAppId AND Status = 0
        UNION ALL
        Select Status from tblSiteMaster where SiteId = @SiteId AND Status = 0
        UNION ALL
        Select Status from tblCompetency where CompetencyId = @CompetencyID AND Status = 0  
        UNION ALL
        Select Status from Estaff where EStaffId = @EstaffId AND Status = 0
        UNION ALL
        Select Status from CostCenter where CostCenterId = @CostCenterId AND Status = 0 
        UNION ALL
        Select Status from PlanViewLocationMaster where PlanviewLocationID = @PVLocationId AND Status = 0
   ) U
)

可能不需要

SELECT TOP 1 *
级别,因为我预计
EXISTS(...)
测试也会快捷。这将简化查询,如下所示。

UPDATE I
SET Status = 2
FROM InputResource I
WHERE I.EFITID = 214
AND EXISTS (
    Select ...
)

另一个等效的替代方法是使用

CROSS APPLY
代替
EXISTS()
。 CROSS APPLY 就像子选择的内部联接。如果没有匹配到内层行,则丢弃外层行。

UPDATE I
SET Status = 2
FROM InputResource I
CROSS APPLY (
    SELECT TOP 1 *
    FROM (
        Select ...
   ) U
) C
WHERE I.EFITID = 214

无论如何,我都会鼓励进行测试,以确保结果具有预期的性能,并且快捷逻辑已到位,以避免不必要的子查询执行。 (如果您设置第一个或第二个子选择全部匹配的场景,则执行计划应显示其他选择访问的零行。)

最后,仔细检查这些子查询中引用的表是否有适当的索引。大多数看起来像 PK 查找,所以你可能很好。

© www.soinside.com 2019 - 2024. All rights reserved.