递归 cte 查询 |创建多个编号行 | Sql-服务器

recursive cte query | Creating multiple numbered rows | Sql-server

我正在尝试使用数字 09000000000000000000000000007165 中的字段来完成 table 中的一列 到号码 0900000000000000000000000008165

我有一个问题,这些数字对于这段代码来说太大了,我不知道如何处理它

类型: ID - varchar(31)

错误:(翻译)

Msg 240, Level 16, State 1, Line 3 Type mismatch between the anchor and the cyclic part in the "start" column of the cyclic "cter" query.

  with cter as (
     select 0900000000000000000000000007165 as start, 0900000000000000000000000008165 as loop_end
     union all
     select c.start + 1, loop_end
     from cter c
     where c.start < loop_end
)

INSERT INTO [Base].[dbo].[Table] (Id)
   select c.start
   from cter c
   option (maxrecursion 0);

我最初尝试使用 BIGINT 并遇到算术溢出错误。后来用NUMBERIC(30,0)修改,感谢Larnu。我能够得到正确的结果。

DECLARE @loop_start CHAR(31) = '0900000000000000000000000007165'
, @loop_end CHAR(31) = '0900000000000000000000000008165'
;with cter as 
(
     select CAST(@loop_start as numeric(30,0)) as start, CAST(@loop_end as numeric(30,0)) loop_end
     union all
     select cast((c.start +1) as numeric(30,0)) , cast(loop_end as numeric(30,0))
     from cter c
     where c.start < loop_end
)

   select  c.start
   from cter c
   option (maxrecursion 0);

结果集为:

+---------------------------------+
| 900000000000000000000000007165 |
| 900000000000000000000000007166 |
|                               . |
|                               . |
|                               . |
| 900000000000000000000000008163 |
| 900000000000000000000000008164 |
| 900000000000000000000000008165 |
+---------------------------------+

问题其实如报错所示,递归CTE的上半部分和下半部分的数据类型不同:

SELECT [name],system_type_name
FROM sys.dm_exec_describe_first_result_set('select 0900000000000000000000000007165 as start, 0900000000000000000000000008165 as loop_end',NULL,NULL);

这为您提供了两个值的 numeric(30,0)。另一方面,如果你检查底部,你会得到不同的结果:

SELECT [name],system_type_name
FROM sys.dm_exec_describe_first_result_set('SELECT sq.start +1 AS Start, sq.loop_end FROM(select 0900000000000000000000000007165 as start, 0900000000000000000000000008165 as loop_end) sq',NULL,NULL);

此处,Start 的数据类型为 numeric(31,0),与顶层不同

但是,为了扩展我的评论,您最好在此处使用 Tally。这实际上可以完全避免错误,因为没有递归 CTE,而且速度要快得多:

DECLARE @Start numeric(30,0),
        @End numeric(30,0);

SET @Start = 0900000000000000000000000007165;
SET @End = 0900000000000000000000000008165;

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (CONVERT(bigint,@End - @Start))
           ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1, N N2, N N3, N N4) --This will produce up 10,000 rows. CROSS JOIN to N more for more rows.
INSERT INTO Base.dbo.[Table] (ID)
SELECT RIGHT(CONCAT(REPLICATE('0',31),T.I + @Start),31)
FROM Tally T;