While 循环作为游标

While Loop as a Cursor

我的案例是一个典型的研究案例,可以很容易地通过游标构造来解决,但我的问题是为什么我的说法只有在下面提到的情况下才是正确的?刹车越多,说明效果越差。也许,我使用的临时 table 完全不需要?确实,我的概念有逻辑错误。

通常我有一个 table MJ_IDT 其中:

  1. identity_col 是数据类型 int identity(1,1)
  2. data_col 是数据类型 int,它允许空值

    identity_col data_col 1 个 AAAAA 2 中国商会 3 BBBB 5 ddddd

我想准备一个 while 循环,它的任务是找到所有制动器并用适当的值填充它,在这种情况下将是一对 4 NULL。

我另外创建了一个临时 table #mj_id,它在我的 sql 语句中使用如下。

id  id_col
1   1
2   2
3   3
4   5

我的sql查询:

CREATE TABLE #mj_id
(
    id int identity(1,1),
    id_col int NULL
)

INSERT INTO #mj_id (id_col)
SELECT identity_col FROM MJ_IDT

DECLARE 
    @counter_next   int = 1,
    @incremental    int = 1,
    @counter_prev   int = 0;

WHILE EXISTS (SELECT top 1 1 FROM #mj_id 
              WHERE id = @counter_next) 
  AND @counter_next < (SELECT MAX(identity_col) FROM MJ_IDT)
BEGIN   
    IF (SELECT id_col FROM #mj_id 
        WHERE id = @counter_next) - @counter_prev > @incremental
    BEGIN
        SET IDENTITY_INSERT MJ_IDT ON;

        INSERT INTO MJ_IDT (identity_col)
        VALUES (@counter_next);

        SET @counter_prev = (SELECT id_col FROM #mj_id 
                             WHERE id = @counter_next);
        SET @counter_next = @counter_next + @incremental;

        SET IDENTITY_INSERT MJ_IDT OFF;
    END
    ELSE
       SET @counter_prev = (SELECT id_col FROM #mj_id 
                            WHERE id = @counter_next);
       SET @counter_next = @counter_next + @incremental;
    END

它在这种情况下有效,但是当我的 table MJ_IDT 是:

1   AAAAA
2   CCCCC
3   BBBBB
5   ddddd
6   ggggg
8   ggggg

它不工作。你能帮我填补身份列的刹车吗?

需要注意的重要注意事项:

从你的问题来看,你似乎在尝试识别和纠​​正自动生成的 identity 值中的差距。这是毫无意义的努力,因为 identity 值不能保证是连续的,只是唯一的。


您问题的实际答案:

您不需要游标或循环,只需 table 到 join 的数字即可为您填补空白。您可以使用计数 table:

构建其中之一
declare @MJ_IDT table (identity_col int, data_col nvarchar(10));
insert into @MJ_IDT values(1,'AAAAA'),(2,'CCCCC'),(3,'BBBBB'),(5,'ddddd');

              -- Create table with 10 rows in it:
with t(t) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)
              -- Cross join this table to exponentially increase the number of rows,
              -- then return the row_number of enough rows to cover up to your max ID:
    ,n(n) as (select top (select max(identity_col) from @MJ_IDT) row_number() over (order by (select null))
              from t t1,t t2,t t3,t t4,t t5,t t6
             )
select n.n as identity_col
        ,m.data_col
from n
    left join @MJ_IDT m
        on(n.n = m.identity_col)
order by n.n;

输出:

+--------------+----------+
| identity_col | data_col |
+--------------+----------+
|            1 | AAAAA    |
|            2 | CCCCC    |
|            3 | BBBBB    |
|            4 | NULL     |
|            5 | ddddd    |
+--------------+----------+