使用存储过程(+1或-1)表中的值

时间:2012-11-20 12:43:13

标签: asp.net sql-server

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

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

在我看来,我需要获取当前值,添加一个,然后将其保存在表中,将我带到此代码:

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.

4 个答案:

答案 0 :(得分:2)

SET @count = UserCount 

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

你可以在一个原子语句中完成所有操作。这会使列递增,并使用UserCount的新值设置输出参数。

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

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

答案 1 :(得分:1)

对于参考案例,它应该是这样的

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 < @MaxUserCount。由于页面快速刷新[竞争条件],您的存储过程可能无法捕获所有计数。你可能有一个旧的@Count值。

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

无需使用临时变量和使用select查询。 试试这个..

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