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

SQL Server中WHILE循环实现变量名递减的问题

解决SQL Server WHILE循环中动态获取递减变量值的问题

问题分析

你当前通过CONCAT('@chk', @task_total)生成的是字符串(比如'@chk3'),而非变量@chk3的实际值,因此需要一种方式根据@task_total的数值匹配到对应变量的内容。

解决方案

方法1:使用CASE表达式(推荐,适合变量数量固定的场景)

由于你的变量仅包含@chk1、@chk2、@chk3三个,直接用CASE表达式根据@task_total的数值返回对应变量的值即可,无需动态拼接变量名,简单高效。

修改后的代码如下:

DECLARE @chk1 VARCHAR(3), @chk2 VARCHAR(3), @chk3 VARCHAR(3)
DECLARE @task_total INT, @tasknum INT, @next_evtcode VARCHAR(10), @ot_desc VARCHAR(100)
DECLARE @ot_dates VARCHAR(10), @ot_object VARCHAR(50), @ot_createdby VARCHAR(50), @tasklist VARCHAR(50)

SET @chk1 = 'YES'
SET @chk2 = 'YES'
SET @chk3 = 'NO'

SELECT @task_total = COUNT(*) 
FROM R5TASKCHECKLISTS 
WHERE TCH_TASK = @tasknum

-- 循环从@task_total开始,直到1(无@chk0变量,避免无效循环)
WHILE @task_total >= 1
BEGIN
    DECLARE @chk_current VARCHAR(3)
    -- 通过CASE匹配对应变量的值
    SET @chk_current = CASE @task_total
        WHEN 3 THEN @chk3
        WHEN 2 THEN @chk2
        WHEN 1 THEN @chk1
    END

    INSERT INTO R5TRACKINGDATA
        (TKD_TRANS, TKD_TRACKDATE,
         TKD_PROMPTDATA1, TKD_PROMPTDATA2, TKD_PROMPTDATA3,
         TKD_PROMPTDATA4, TKD_PROMPTDATA5, TKD_PROMPTDATA6,
         TKD_PROMPTDATA7, TKD_PROMPTDATA8, TKD_PROMPTDATA9,
         TKD_PROMPTDATA10, TKD_PROMPTDATA11, TKD_PROMPTDATA12,
         TKD_PROMPTDATA13, TKD_PROMPTDATA14, TKD_PROMPTDATA15) 
    VALUES ('AO01',   --TKD_TRANS
            GETDATE(),
            @next_evtcode,    -- EVT_CODE
            @ot_desc,         -- EVT_DESC
            @ot_dates,        -- EVT_DATE (dd/mm/yyyy)
            '100',            -- EVT_MRC
            '282',            -- EVT_ORG
            'PMM',            -- EVT_JOBTYPE
            @ot_dates,        -- EVT_REPORTED (dd/mm/yyyy)
            @ot_object,       -- EVT_OBJECT
            '282',            -- EVT_OBJECT_ORG
            @ot_dates,        -- EVT_TARGET (dd/mm/yyyy)
            @ot_dates,        -- EVT_COMPLETED (dd/mm/yyyy)
            @ot_createdby,    -- EVT_ENTEREDBY
            @tasklist,        -- TSK_CODE
            @task_total,      -- ACK_SEQUENCE
            @chk_current      -- ACK_NO_YES (NO or YES)
        )

    SET @task_total = @task_total - 1;
END

方法2:使用动态SQL(适合变量数量不固定的场景)

如果后续可能新增更多@chkN类型的变量,可以用动态SQL拼接执行语句,注意变量传递的处理:

DECLARE @chk1 VARCHAR(3), @chk2 VARCHAR(3), @chk3 VARCHAR(3)
DECLARE @task_total INT, @tasknum INT, @next_evtcode VARCHAR(10), @ot_desc VARCHAR(100)
DECLARE @ot_dates VARCHAR(10), @ot_object VARCHAR(50), @ot_createdby VARCHAR(50), @tasklist VARCHAR(50)
DECLARE @sql NVARCHAR(MAX)

SET @chk1 = 'YES'
SET @chk2 = 'YES'
SET @chk3 = 'NO'

SELECT @task_total = COUNT(*) 
FROM R5TASKCHECKLISTS 
WHERE TCH_TASK = @tasknum

WHILE @task_total >= 1
BEGIN
    -- 拼接动态SQL语句,代入对应变量值
    SET @sql = N'
    INSERT INTO R5TRACKINGDATA
        (TKD_TRANS, TKD_TRACKDATE,
         TKD_PROMPTDATA1, TKD_PROMPTDATA2, TKD_PROMPTDATA3,
         TKD_PROMPTDATA4, TKD_PROMPTDATA5, TKD_PROMPTDATA6,
         TKD_PROMPTDATA7, TKD_PROMPTDATA8, TKD_PROMPTDATA9,
         TKD_PROMPTDATA10, TKD_PROMPTDATA11, TKD_PROMPTDATA12,
         TKD_PROMPTDATA13, TKD_PROMPTDATA14, TKD_PROMPTDATA15) 
    VALUES (''AO01'',   --TKD_TRANS
            GETDATE(),
            @next_evtcode,    -- EVT_CODE
            @ot_desc,         -- EVT_DESC
            @ot_dates,        -- EVT_DATE (dd/mm/yyyy)
            ''100'',            -- EVT_MRC
            ''282'',            -- EVT_ORG
            ''PMM'',            -- EVT_JOBTYPE
            @ot_dates,        -- EVT_REPORTED (dd/mm/yyyy)
            @ot_object,       -- EVT_OBJECT
            ''282'',            -- EVT_OBJECT_ORG
            @ot_dates,        -- EVT_TARGET (dd/mm/yyyy)
            @ot_dates,        -- EVT_COMPLETED (dd/mm/yyyy)
            @ot_createdby,    -- EVT_ENTEREDBY
            @tasklist,        -- TSK_CODE
            ' + CAST(@task_total AS NVARCHAR) + ',      -- ACK_SEQUENCE
            ' + CASE @task_total
                WHEN 3 THEN '''NO'''
                WHEN 2 THEN '''YES'''
                WHEN 1 THEN '''YES'''
            END + '      -- ACK_NO_YES (NO or YES)
        )'
    
    -- 执行动态SQL,传递外部变量
    EXEC sp_executesql @sql, 
        N'@next_evtcode VARCHAR(10), @ot_desc VARCHAR(100), @ot_dates VARCHAR(10), @ot_object VARCHAR(50), @ot_createdby VARCHAR(50), @tasklist VARCHAR(50)',
        @next_evtcode = @next_evtcode,
        @ot_desc = @ot_desc,
        @ot_dates = @ot_dates,
        @ot_object = @ot_object,
        @ot_createdby = @ot_createdby,
        @tasklist = @tasklist

    SET @task_total = @task_total - 1;
END

注意事项

  • 方法1更简洁,性能更优,无需动态编译SQL,完全适配你当前的固定变量场景。
  • 原代码循环条件@task_total >=0会触发无对应变量的无效循环,已调整为@task_total >=1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:55:38