使用带/ inner连接的存储过程从数据库计数数据

时间:2012-09-25 13:13:09

标签: c# asp.net

我在使用内连接计算数据时遇到问题。

我想算一下有多少小屋,这是我的桌子:

enter image description here

enter image description here

这是我在课堂上获取山寨号的代码。

public void CheckCottages()
 {
     con.Close();
     SqlCommand comUmbrella = new SqlCommand("CountCottages", con);
     comUmbrella.CommandType = CommandType.StoredProcedure;
     comUmbrella.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Umbrella";
     comUmbrella.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comUmbrella.ExecuteNonQuery();
     drUmbrella = comUmbrella.ExecuteReader();
     if (drUmbrella.Read())
     {
         this.UMBRELLA = drUmbrella.GetInt32(drUmbrella.GetOrdinal("Rows"));
     }
     con.Close();
     SqlCommand comNativeKubo = new SqlCommand("CountCottages", con);
     comNativeKubo.CommandType = CommandType.StoredProcedure;
     comNativeKubo.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Native Kubo";
     comNativeKubo.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comNativeKubo.ExecuteNonQuery();
     drKubo = comNativeKubo.ExecuteReader();
     if (drKubo.Read())
     {
         this.NATIVEKUBO = drKubo.GetInt32(drKubo.GetOrdinal("Rows"));
     }
     con.Close();
     SqlCommand comTreeHouse = new SqlCommand("CountCottages", con);
     comTreeHouse.CommandType = CommandType.StoredProcedure;
     comTreeHouse.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Tree house";
     comTreeHouse.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comTreeHouse.ExecuteNonQuery();
     drTree = comTreeHouse.ExecuteReader();
     if (drTree.Read())
     {
         this.TREEHOUSE = drTree.GetInt32(drTree.GetOrdinal("Rows"));
     }
     con.Close();
     SqlCommand comPavillion = new SqlCommand("CountCottages", con);
     comPavillion.CommandType = CommandType.StoredProcedure;
     comPavillion.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Pavillion";
     comPavillion.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comPavillion.ExecuteNonQuery();
     drPavillion = comPavillion.ExecuteReader();
     if (drPavillion.Read())
     {
         this.PAVILLION = drPavillion.GetInt32(drPavillion.GetOrdinal("Rows"));
     }
 }

这是我存储的程序:

ALTER PROCEDURE dbo.CountCottages
(
    @CottageType nvarchar(50),
    @ReservedDate datetime
)

AS
SELECT count(dbo.Cottages.CottageName)
FROM dbo.Cottages INNER JOIN
dbo.ResortTransactions ON dbo.Cottages.CottageID = dbo.ResortTransactions.CottageID
where dbo.Cottages.CottageType=@CottageType and dbo.ResortTransactions.Status != 'Cancelled' and dbo.ResortTransactions.ReservedDate != @ReservedDate

RETURN

我的代码出了什么问题?我希望有人可以帮助我:)。

提前致谢!

4 个答案:

答案 0 :(得分:3)

由于没有太多关于如何使用数据的信息,所以这是一个猜测。我假设你想要一个小屋,其中有一个交易,其中1)状态未被取消,2)日期等于预订日期。如果是这样,这是查询:

SELECT count(dbo.Cottages.CottageName)
    FROM dbo.Cottages 
    WERE CottageType=@CottageType 
        AND CottageID NOT IN
        (SELECT CottageID FROM dbo.ResortTransactions
         WHERE Status != 'Cancelled' 
         AND ReservedDate = @ReservedDate)

此外,您正在执行sproc两次 - 一次使用ExecuteNonQuery,一次使用ExecuteReader您应该返回一个值并使用ExecuteNonQuery,创建一个参数存储返回值,或使用ExecuteScalar快速从数据集中提取第一个结果。

我建议阅读更多有关基本SQL以及如何使用.NET执行查询的内容。

答案 1 :(得分:1)

您没有返回COUNT

声明一个变量,用结果初始化它并从过程中返回它:

ALTER PROCEDURE dbo.CountCottages
(
    @CottageType nvarchar(50),
    @ReservedDate datetime
)
AS
BEGIN

DECLARE @NumCottages int
SELECT @NumCottages = count(dbo.Cottages.CottageName)
FROM dbo.Cottages INNER JOIN
dbo.ResortTransactions ON dbo.Cottages.CottageID = dbo.ResortTransactions.CottageID
where dbo.Cottages.CottageType=@CottageType and dbo.ResortTransactions.Status != 'Cancelled' and dbo.ResortTransactions.ReservedDate != @ReservedDate

RETURN @NumCottages

END

然后使用SqlCommand.ExecuteScalar代替ExecuteNonQuery来获取值。

答案 2 :(得分:1)

Cmd.ExeceuteNonQuery()通常用于执行过程而不期望返回结果。 但是在这里你正在寻找一个标量值。所以将它改为cmd.ExecuteScalar()。同时从程序中返回计数。

答案 3 :(得分:0)

我会做一些假设 - 在玩这个时只是一个小小的提示我会在SQL查询中创建一个“便笺簿”并使用表变量进行测试,如下所示:

DECLARE @Cottages AS TABLE
    (
      Cottage_PK INT IDENTITY(1, 1) ,
      CottageName VARCHAR(100) ,
      CottageType VARCHAR(100)
    )
DECLARE @Reservations AS TABLE
    (
      Reservation_PK INT IDENTITY(1, 1) ,
      Cottage_FK INT ,
      CheckinDate DATETIME ,
      DepatureDate DATETIME ,
      IsCanceled BIT
    )
DECLARE @DateToCheck AS DATETIME ,
    @CottageType AS VARCHAR(100)
SET @DateToCheck = '2012-09-15'
SET @CottageType = 'Some Type'
INSERT  INTO @Cottages
        ( CottageName, CottageType )
VALUES  ( 'CottageA', 'Some Type' )
INSERT  INTO @Reservations
        ( Cottage_FK ,
          CheckinDate ,
          DepatureDate ,
          [Status]
        )
VALUES  ( 1 , -- Cottage_FK - int
          '2012-09-16' , -- CheckinDate - datetime
          '2012-09-24' ,  -- DepatureDate - datetime
          ''
        )

现在我假设如果你想检查一个日期可用的小屋,你需要根据签入日期和使用between声明的签名日期进行检查。

SELECT  COUNT(c.CottageName) AS 'Cottages availible'
FROM    @Cottages c
        INNER JOIN @Reservations r ON c.Cottage_PK = r.Cottage_FK
WHERE   NOT @DateToCheck BETWEEN r.CheckinDate
                         AND     r.DepatureDate
        AND c.[status] != 'Cancelled'
        AND c.CottageType = @CottageType

使用它进行测试 - 我在它返回的范围内传递了一个日期0并超出范围并返回1.一旦你高兴地将它移到你的存储过程。

CREATE PROCEDURE dbo.CountCottages
    @DateToCheck DATETIME ,
    @CottageType VARCHAR(100)
AS 
    SELECT  COUNT(c.CottageName) AS 'Cottages availible'
    FROM    Cottages c
            INNER JOIN ResortTransactions r ON c.Cottage_PK = r.Cottage_FK
    WHERE   NOT @DateToCheck BETWEEN r.CheckinDate
                             AND     r.DepatureDate
            AND c.[status] != 'Cancelled'
            AND c.CottageType = @CottageType