TSQL:避免内联函数中的 MAXRECURSION 限制
TSQL: avoid MAXRECURSION limit in a inline function
我有这个功能,给定初始日期和最终日期给出该范围内的相应 year/month:
CREATE FUNCTION [dbo].[fnYearMonth]
(
@Initial Date,
@Final Date
)
RETURNS TABLE
AS
RETURN
With dateRange(StatDate) as
(
select @Initial
union all
select dateadd(month, 1, StatDate)
from dateRange
where dateadd(month, 1, StatDate) <= CAST(DATEADD(month,DATEDIFF(month,0,@Final)+1,0)-1 as Date)
)
select DATEPART(year, StatDate) AS MyYear, DATEPART(month, StatDate) AS MyMonth From dateRange where StatDate <= @Final
问题是 MAXRECURSION 的默认限制为 100 只能使可用日期范围最长为 8 年零 4 个月。那是不够的。
我尝试在使用此函数的函数中使用 "OPTION (MAXRECURSION 2000);",但没有成功,因为我在 WITH 语句中调用了此函数。
我现在唯一的解决办法就是把这个内联函数变成一个多语句函数并使用"OPTION (MAXRECURSION 2000);"。但出于性能原因,我宁愿避免使用此选项。 ¿还有其他选择吗?
感谢您的帮助。
尝试在底部添加 OPTION (MAXRECURSION 0)
或您希望的递归限制,如下所示..
您也可以使用 Calendar table 来避免所有这些给出您需要的输出的计算..
我的数据库中有一个日历 table,输出很容易计算,如下所示。我建议使用 table 而不是重复计算
select distinct month,year from dbo.calendar
where dAte>=getdate()-200 and date<=getdate()
如果您想使用递归选项,请添加 option(recursion)
如下所示
--这不适用于内联 table 值函数,请参见下面的演示
改变功能 [dbo].[fnYearMonth]
(
@初始日期时间,
@Final 日期时间
)
RETURNS TABLE
作为
RETURN
以日期范围为
(
select @Initial as statdate
联合所有
select dateadd(月, 1, StatDate)
从日期范围
其中 dateadd(month, 1, StatDate) <= CAST(DATEADD(month,DATEDIFF(month,0,@Final)+1,0)-1 as Datetime)
)
select DATEPART(year, StatDate) AS MyYear, DATEPART(month, StatDate) AS MyMonth
从日期范围
其中 StatDate <= @Final
选项(最大递归 0);
更新:
MAX 递归选项不适用于内联 table 值函数,它仅适用于多 table 值函数..
演示:
alter function
dbo.getnum_test
(
@n int
)
returns table
as return
With cte as
(
select @n as n
union all
select @n+1
from cte
)
select * from cte
where n<1000
option (maxrecursion 0)
alter function dbo.itvftest
(
@n int
)
returns
@numbers table
(
n int
)
as
begin
With cte as
(
select @n as n
union all
select n+1
from cte
where cte.n<10000
)
Insert into @numbers
select * from cte
where n<1000
option (maxrecursion 0)
return
end
我有这个功能,给定初始日期和最终日期给出该范围内的相应 year/month:
CREATE FUNCTION [dbo].[fnYearMonth]
(
@Initial Date,
@Final Date
)
RETURNS TABLE
AS
RETURN
With dateRange(StatDate) as
(
select @Initial
union all
select dateadd(month, 1, StatDate)
from dateRange
where dateadd(month, 1, StatDate) <= CAST(DATEADD(month,DATEDIFF(month,0,@Final)+1,0)-1 as Date)
)
select DATEPART(year, StatDate) AS MyYear, DATEPART(month, StatDate) AS MyMonth From dateRange where StatDate <= @Final
问题是 MAXRECURSION 的默认限制为 100 只能使可用日期范围最长为 8 年零 4 个月。那是不够的。
我尝试在使用此函数的函数中使用 "OPTION (MAXRECURSION 2000);",但没有成功,因为我在 WITH 语句中调用了此函数。
我现在唯一的解决办法就是把这个内联函数变成一个多语句函数并使用"OPTION (MAXRECURSION 2000);"。但出于性能原因,我宁愿避免使用此选项。 ¿还有其他选择吗?
感谢您的帮助。
尝试在底部添加 OPTION (MAXRECURSION 0)
或您希望的递归限制,如下所示..
您也可以使用 Calendar table 来避免所有这些给出您需要的输出的计算..
我的数据库中有一个日历 table,输出很容易计算,如下所示。我建议使用 table 而不是重复计算
select distinct month,year from dbo.calendar
where dAte>=getdate()-200 and date<=getdate()
如果您想使用递归选项,请添加 option(recursion)
如下所示
--这不适用于内联 table 值函数,请参见下面的演示 改变功能 [dbo].[fnYearMonth] ( @初始日期时间, @Final 日期时间 ) RETURNS TABLE 作为 RETURN 以日期范围为 ( select @Initial as statdate 联合所有 select dateadd(月, 1, StatDate) 从日期范围 其中 dateadd(month, 1, StatDate) <= CAST(DATEADD(month,DATEDIFF(month,0,@Final)+1,0)-1 as Datetime) ) select DATEPART(year, StatDate) AS MyYear, DATEPART(month, StatDate) AS MyMonth 从日期范围 其中 StatDate <= @Final 选项(最大递归 0);
更新: MAX 递归选项不适用于内联 table 值函数,它仅适用于多 table 值函数..
演示:
alter function
dbo.getnum_test
(
@n int
)
returns table
as return
With cte as
(
select @n as n
union all
select @n+1
from cte
)
select * from cte
where n<1000
option (maxrecursion 0)
alter function dbo.itvftest
(
@n int
)
returns
@numbers table
(
n int
)
as
begin
With cte as
(
select @n as n
union all
select n+1
from cte
where cte.n<10000
)
Insert into @numbers
select * from cte
where n<1000
option (maxrecursion 0)
return
end