【问题标题】:Using a stored procedure to (+1 or -1) a value from a table使用存储过程来(+1 或 -1)表中的值
【发布时间】:2012-11-20 12:43:12
【问题描述】:

我有一个按钮事件必须在达到一定数量的用户后自行禁用。

我们正在将当前访问的用户计数存储在数据库中,并且我正在尝试创建一个存储过程,当调用该存储过程时,它将自动增加该表上的用户计数。
我将创建一个单独的减法程序。

在我看来,我需要获取当前值,加一,然后将其保存在表中,从而得到以下代码:

CREATE PROCEDURE procDrRefBooksAddUser 
    -- Add the parameters for the stored procedure here
    @fileId int = NULL,
    @count int = 0,
    @newCount int OUTPUT
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    SELECT UserCount FROM tblDrRefBooks WHERE DrRefBookFileID = @fileId
    SET @count = UserCount

    SET @newCount = @count + 1

    -- Insert statements for procedure here
    UPDATE tblDrRefBooks SET tblDrRefBooks.UserCount = @newCount WHERE DrRefBookFileID = @fileId
END

不幸的是,我无法正确处理,出现以下错误:

Msg 207, Level 16, State 1, Procedure procDrRefBooksAddUser, Line 17
Invalid column name 'UserCount'

谁能告诉我哪里出错了。

编辑:更新答案(最终)

我的 SQL 是:

ALTER PROCEDURE [dbo].[procDrRefBooksAddUser] 
    -- Add the parameters for the stored procedure here
    @fileId int = NULL,
    @newCount int OUTPUT
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    -- SET NOCOUNT ON;

    UPDATE tblDrRefBooks
    SET @newCount = UserCount = UserCount + 1
    WHERE DrRefBookFileID = @fileId
    SELECT @newCount AS iden

END

后面的代码是:

 using (SqlConnection db = DataConn.SqlConnection())
                {
                    db.Open();
                    SqlTransaction transaction = db.BeginTransaction();

                    try
                    {
                        lbltest.Text = "Starting...";
                       using (SqlCommand acommand =
                            new SqlCommand(
                                "EXEC procDrRefBooksAddUser @fileID, @count",
                                db, transaction) { CommandType = CommandType.Text })
                        {
                            acommand.Parameters.Add(new SqlParameter("@fileID", SqlDbType.Int)).Value = Int32.Parse(location.Value);
                            acommand.Parameters.Add(new SqlParameter("@count", SqlDbType.Int) { Direction = ParameterDirection.Output });

                            using (SqlDataReader rdr = acommand.ExecuteReader())
                            {
                                btnLoad.Text = "Here: " + rdr["iden"];
                            }
                        }

                        transaction.Commit();
                    }
                    catch (Exception ea)
                    {
                        transaction.Rollback();
                        lbltest.Text = ("Insertion Error: " + ea.Message);
                    }
                }

但我收到此错误:Insertion Error: Invalid attempt to read when no data is present.

【问题讨论】:

    标签: asp.net sql-server


    【解决方案1】:
    SET @count = UserCount 
    

    不正确。您无法访问以前的 SELECT 类似的语句中的列。

    您可以在一个原子语句中完成所有操作。这会增加列并将输出参数设置为 UserCount 的新值。

    UPDATE tblDrRefBooks
    SET    @newCount = UserCount = UserCount + 1
    WHERE  DrRefBookFileID = @fileId 
    

    这避免了在单独的操作中读取和写入值的竞争条件。

    【讨论】:

    • 似乎合法 :/ 只是试图让我的代码正确地发出语句,然后我会标记答案^^
    • 当试图读取 @newCount (as iden) - 它说 Invalid attempt to read when no data is present
    • @NewAmbition 您不需要使用 DataReader,因为它不返回任何结果集。只需使用 ExecuteNonQuery 然后从输出参数中获取值
    • @MartinSmith - 我想我以前的Output Parameter 使用过阅读器 - 我不知道任何其他方式。
    【解决方案2】:

    在您的程序中使用以下代码:

    SELECT @count=UserCount FROM tblDrRefBooks WHERE DrRefBookFileID = @fileId

    【讨论】:

      【解决方案3】:

      参考案例应该是这样的

      SELECT @Count = UserCount FROM tblDrRefBooks WHERE DrRefBookFileID = @fileId
      @newCount = @Count + 1
      

      但你可以避免这种情况,而是这样做

      UPDATE tblDrRefBooks SET UserCount = UserCount + 1
      WHERE 
         DrRefBookFileID = @fileId AND
         UserCount < @MaxUserCount
      

      更新

      注意我添加了AND UserCount &lt; @MaxUserCount。随着页面快速刷新[竞争条件],您的存储过程可能无法捕获所有计数。您可能有一个旧的 @Count 值。

      • 确保计数仅在未达到 MAX 时增加
      • 只需使用另一个 PROC 在任何时间点获取计数。不要在与更新计数相同的 PROC 中执行此操作,因为您可以获得 OLD 计数值
      • 可以在您的表上设置一个标志,一旦达到 MAX,该标志就会在 PROC 中设置

      【讨论】:

        【解决方案4】:

        不需要使用临时变量和使用选择查询。 试试这个。。

        UPDATE tblDrRefBooks 
        SET tblDrRefBooks.UserCount = UserCount +1 
        WHERE DrRefBookFileID = @fileId
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-05-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-03
          相关资源
          最近更新 更多