рекурсивный cte запрос | Создание нескольких пронумерованных строк | Sql -server - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь заполнить столбец в таблице полями от номера 0900000000000000000000000007165 до номера 0900000000000000000000000008165

У меня проблема в том, что это слишком большие числа для этого куска кода, я понятия не имею, что что с ним делать

Тип: Id - varchar (31)

Ошибка: (перевод)

Сообщение 240, Уровень 16, Состояние 1, Тип линии 3 несоответствие между якорем и частью cycli c в столбце "start" запроса cycli c "cter".

  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);

Ответы [ 2 ]

4 голосов
/ 20 марта 2020

Проблема на самом деле, как предполагает ошибка, типы данных верхней части рекурсивного 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), который отличается от верхнего уровня .

Но, если углубиться в мой комментарий, вам лучше воспользоваться подсчетом здесь. Это на самом деле полностью исключит ошибку, так как нет рекурсивного 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;
1 голос
/ 20 марта 2020

Я изначально пытался с BIGINT и получил арифметику c ошибка переполнения. Позже, модифицированный с NUMBERI C (30,0), спасибо Ларну. Я могу получить правильный результат.

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 |
+---------------------------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...