【问题标题】:The maximum recursion 100 has been exhausted before statement completion using SQL Function在使用 SQL 函数完成语句之前,最大递归 100 已用完
【发布时间】:2017-04-04 15:12:16
【问题描述】:

我已经创建了用于将日期输入到我的 Gridview 中的 SQL 函数,因此我将开始日期和结束日期传递给我的函数,但出现如下错误。

The maximum recursion 100 has been exhausted before statement completion

如果计数日期大于 100 意味着出现上述错误,如果低于 100 意味着没有出现任何错误。我有超过 100 天的记录。

下面是我的数据逻辑。

 public DataTable GetDates(DateTime StartDate, DateTime EndDate)
  {
    DataTable dt = new DataTable();// order by dt desc
    ConnectMethod();
    cmd = new SqlCommand("select dt from dbo.ExplodeDates(@StartDate,@EndDate) order by dt desc", con);
    try
    {
        cmd.CommandType = CommandType.Text;
        cmd.Parameters.AddWithValue("@StartDate", StartDate);
        cmd.Parameters.AddWithValue("@EndDate", EndDate);
        cmd.ExecuteScalar();
        SqlDataAdapter da = new SqlDataAdapter(cmd);

        da.Fill(dt);
        return dt;
    }
    catch (Exception ex)
    { return dt; }
    finally
    {
        con.Close();
        con.Dispose();
        cmd.Dispose();
    }
} 

我在 cmd.ExecuteScalar(); 上收到此错误;线。 下面是我的 SQL 函数。

  CREATE FUNCTION [dbo].[ExplodeDates](
    @startdate datetime
    , @enddate datetime
   )
  RETURNS TABLE
  AS
  RETURN
    WITH DATES AS(
            SELECT @startdate AS dt
            UNION ALL
            SELECT DATEADD(D, 1, dt) FROM DATES WHERE DT<@enddate
    )
    SELECT * FROM DATES

     GO

请帮助解决这个问题,从早上开始查看结果。

【问题讨论】:

  • 只是不要那样做。创建一个包含大量年份的日历表。每年只有 365 行,它不占用空间但极大地提高了性能
  • 我的网站已经上线,请帮助如何仅修改此代码或更新您的答案。 @Panagiotis Kanavos
  • 查看 Aaron Bertrand 的 Creating a date dimension or calendar table in SQL Server。 50 年的日期需要 3MB。您可以使用文章的技术来避免递归,但是当您可以简单地从 3MB 表中检索所需的所有日期时计算一个日期范围?
  • 不,我不想要那么多年,我的申请只需要 200 天,我们可以对我的上述相同功能进行 200 天的修改,请帮助。 @Panagiotis Kanavos
  • 阅读文章,它已经包含了你需要的脚本。只需创建一个表并选择只有 200 天

标签: asp.net sql-server sql-server-2008


【解决方案1】:

您可以使用简单的 tally-table-on-the-fly 避免递归 CTE:

DECLARE @NumberOfDays INT=200;
DECLARE @StartDate DATE=GETDATE();

WITH Numbers AS
(SELECT TOP (@NumberOfDays) ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1 AS Nmbr FROM master..spt_values)
SELECT DATEADD(DAY,Nmbr,@StartDate)
FROM Numbers 

master..spt_values 应该包含足够的行 (~2500) 以确保返回 200 行。您可以使用CROSS JOIN master..spt_values AS v2 轻松放大这个数字,这将允许相当大的数字...(超过 6mio)

更新:一个函数

   CREATE FUNCTION [dbo].[ExplodeDates]
   (
      @startdate datetime
    , @enddate datetime
   )
  RETURNS TABLE
  AS
  RETURN
    WITH Numbers AS
    (SELECT TOP (DATEDIFF(DAY,@startdate,@enddate)+1) ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1 AS Nmbr FROM master..spt_values)
    SELECT DATEADD(DAY,Nmbr,@startdate) AS dt
    FROM Numbers;
  GO

  SELECT * FROM dbo.ExplodeDates({d'2017-03-01'},GETDATE());

【讨论】:

  • 为什么每次都这样做而不是创建一次日历表?
  • 这个我必须添加到我的函数中吗? @Shnugo
  • @PanagiotisKanavos 好吧,你是对的,在我的项目中我确实使用日历表 :-D 但是 OP 明确告诉,不应该创建物理存储的表 - 为什么... 这种方法是(几乎)闪电般的速度......足够快以满足大多数需求。顺便说一句:master..spt_values 是一个物理存储的表...... :-D
  • PanagiotisKanavos 我不想要 50 年,所以只需要 200 天的日期。 @Shnugo
  • @mazhar124 你用我的代码替换你的函数代码。您可以将@NumberOfDays 替换为简单的DATEDIFF() 与您的@StartDate@EndDate
【解决方案2】:

您需要在选择表后添加maximum recursion 选项。喜欢:

from DATES
option (maxrecursion 0)

【讨论】:

    猜你喜欢
    • 2017-05-02
    • 2021-09-19
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多