While 循环作为游标
While Loop as a Cursor
我的案例是一个典型的研究案例,可以很容易地通过游标构造来解决,但我的问题是为什么我的说法只有在下面提到的情况下才是正确的?刹车越多,说明效果越差。也许,我使用的临时 table 完全不需要?确实,我的概念有逻辑错误。
通常我有一个 table MJ_IDT 其中:
identity_col
是数据类型 int identity(1,1)
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 |
+--------------+----------+
我的案例是一个典型的研究案例,可以很容易地通过游标构造来解决,但我的问题是为什么我的说法只有在下面提到的情况下才是正确的?刹车越多,说明效果越差。也许,我使用的临时 table 完全不需要?确实,我的概念有逻辑错误。
通常我有一个 table MJ_IDT 其中:
identity_col
是数据类型int identity(1,1)
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 |
+--------------+----------+