Максимальная рекурсия исчерпана
Мне нужен эффективный способ передачи параметра [StartingNumber] и последовательного отсчета от [StartingNumber], пока я не найду пропущенное число.
Я использую следующий sql, чтобы получить следующий номер:
DECLARE @StartOffset int
SET @StartOffset = 23
; With Missing as (
select @StartOffset as N where not exists(
select * from [QUEUE] where QueueNum = @StartOffset AND ismelutash = 1)
), Sequence as
( select @StartOffset as N from [QUEUE] where QueueNum = @StartOffset
union all
select b.QueueNum from [QUEUE] b inner join Sequence s
on b.QueueNum = s.N + 1 and b.ismelutash = 1
)
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence))
Это работало некоторое время, но теперь, когда я запускаю его, я получаю "Утверждение прекращено. Максимальная рекурсия 100 была исчерпана до завершения оператора.'
У кого-нибудь есть идеи? Спасибо
РЕДАКТИРОВАТЬ:
Я добавил maxrecursion, но он просто загружается и не возвращает данные:
DECLARE @StartOffset int
SET @StartOffset = 50
DECLARE @isMelutash int
SET @isMelutash = 0
; With QueueFilters as (
select queuenum from queue where ismelutash = 1
), Missing as (
select @StartOffset as N where not exists(select * from QueueFilters where queuenum = @StartOffset)
), Sequence as (
select @StartOffset as N from QueueFilters where queuenum = @StartOffset
union all
select b.queuenum from QueueFilters b inner join Sequence s on b.queuenum = s.N + 1
)
select COALESCE((select N from Missing ),(select MAX(N)+1 from Sequence ) )
**OPTION(MAXRECURSION 150)**
2 ответа
Вы можете использовать опцию MAXRECURSION в вашем текущем коде
Однако нет необходимости повторять построчно (используя метод Ицик Бен-Гана). Это обнаружит случаи, когда в очереди нет строк с ismelutash = 1, потому что он использует таблицу Tally в качестве ссылочной последовательности.
;WITH
Pass0 as (select 1 as C union all select 1), --2 rows
Pass1 as (select 1 as C from Pass0 as A, Pass0 as B),--4 rows
Pass2 as (select 1 as C from Pass1 as A, Pass1 as B),--16 rows
Pass3 as (select 1 as C from Pass2 as A, Pass2 as B),--256 rows
Pass4 as (select 1 as C from Pass3 as A, Pass3 as B),--65536 rows
Pass5 as (select 1 as C from Pass4 as A, Pass4 as B),--4,294,967,296 rows
Tally as (select row_number() over(order by C) as Number from Pass5)
select TOP 1
Number
from
Tally T
LEFT JOIN --corrected, oops.
[QUEUE] Q ON T.Number = Q.QueueNum AND Q.ismelutash = 1
where
T.Number >= @StartOffset AND T.Number <= 1000000
AND
Q.QueueNum IS NULL
ORDER BY
T.Number
Редактировать:
Оригинальный код с подсказкой MAXRECURSION в конце. Эта ссылка тоже лучше
DECLARE @StartOffset int
SET @StartOffset = 23
; With Missing as (
select @StartOffset as N where not exists(
select * from [QUEUE] where QueueNum = @StartOffset AND ismelutash = 1)
), Sequence as
( select @StartOffset as N from [QUEUE] where QueueNum = @StartOffset
union all
select b.QueueNum from [QUEUE] b inner join Sequence s
on b.QueueNum = s.N + 1 and b.ismelutash = 1
)
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence))
OPTION (MAXRECURSION 0)
Я считаю, что это эквивалентно, и он не использует рекурсию:
SELECT COALESCE(MIN(QueueNum)
, (SELECT Max(QueueNum) + 1
FROM [Queue]
WHERE QueueNum > @StartOffset)
, @StartOffset)
FROM [QUEUE]
WHERE QueueNum >= @StartOffset
AND ismelutash != 1