递归 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;
我正在尝试使用数字 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;