存储过程只返回第一行

时间:2021-01-30 01:30:10

标签: sql-server stored-procedures

我有一个存储过程,用于检查将在接下来的 90、60、30、21、14 和 7 天内到期的卡。当我在 SQL Server 中执行存储过程时,我得到了所有的行,但是当我从代码中调用相同的存储过程时,它只返回第一行而不循环整个结果集。

这是我检索结果的方式:

SELECT AVG(t1.Score * 1.0)

在我调用的代码中:

CREATE PROCEDURE [dbo].[GetExpiringCards] 
AS
    DECLARE @today datetime2 = CAST(GETDATE() AS date)
    DECLARE @INTERVALS TABLE (intval int)

    INSERT INTO @INTERVALS (intval) VALUES (90)
    INSERT INTO @INTERVALS (intval) VALUES (60)
    INSERT INTO @INTERVALS (intval) VALUES (30)
    INSERT INTO @INTERVALS (intval) VALUES (21)
    INSERT INTO @INTERVALS (intval) VALUES (7)
    INSERT INTO @INTERVALS (intval) VALUES (14)

    DECLARE @value int

    DECLARE db_cursor CURSOR FOR  
         SELECT intval FROM @INTERVALS

    OPEN db_cursor   

    FETCH NEXT FROM db_cursor INTO @value   

    WHILE @@FETCH_STATUS = 0 
    BEGIN
        SET NOCOUNT ON;

        SELECT 
            @value AS Interval, DATEADD(DD, @value, @today) AS ExpiresOn, 
            CustomerId, IssueBranch 
        FROM
            Cards 
        WHERE
            ExpiryDate = CONVERT(DATE, DATEADD(DAY, @value, GETDATE()))

        FETCH NEXT FROM db_cursor INTO @value 
    END

    CLOSE db_cursor   
    DEALLOCATE db_cursor
GO

当我在 SSMS 中执行存储过程时,我得到以下信息:

QUERY

我尝试更改如下逻辑,但一旦获取第一行,流程就会立即循环:

   using (SqlConnection conn = new SqlConnection(DatabaseConnect2))
   {
       SqlCommand cmd = new SqlCommand("GetExpiringCards", conn);
       cmd.CommandType = CommandType.StoredProcedure;

       conn.Open();

       SqlDataReader dr = cmd.ExecuteReader();

       while (dr.Read())
       {
           Customer customer = new Customer ();

           customer.Interval = Convert.ToInt32(dr["Interval"]);
           customer.ExpiresOn = Convert.ToDateTime(dr["ExpiresOn"]);
           customer.CustomerId = Convert.ToString(dr["CustomerId"]);
           customer.IssueBranch = Convert.ToString(dr["IssueBranch"]);

           customer.Add(upload);
       }

       conn.Close();
   }

我错过了什么?

1 个答案:

答案 0 :(得分:3)

每个 FETCH 返回一行作为结果集返回给应用程序。尽管您可以更改 C# 代码来处理该问题(即 dr.NextResult()),但最好在单个查询中返回所有行。下面是一个单语句示例,它也使用 table value constructor 代替表变量。

CREATE PROCEDURE [dbo].[GetExpiringCards] 
AS
SET NOCOUNT ON;
SELECT
      i.value AS Interval
    , DATEADD(DD,value,GETDATE()) AS ExpiresOn
    , CustomerId, IssueBranch 
FROM Cards AS c
CROSS JOIN (SELECT value FROM (VALUES(90),(60),(30),(21),(7),(14)) AS intervals(value)) AS i
WHERE c.ExpiryDate=CONVERT(DATE, DATEADD(DAY, i.value, GETDATE()));