简体   繁体   English

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

[英]Using a stored procedure to (+1 or -1) a value from a table

I have a button event that has to disable itself after a certain number of users is reached. 我有一个按钮事件,必须在达到一定数量的用户后自行禁用。

We are storing the currently accessed user count in the db, and I am trying to create a stored procedure, that when called, will automatically increment the user count on that table. 我们将当前访问的用户计数存储在db中,我正在尝试创建一个存储过程,在调用时,它将自动增加该表上的用户计数。
I am going to create a separate procedure to subtract. 我将创建一个单独的程序来减去。

In my mind, I would need to get the current value, add one, then save it in the table, bringing me to this code: 在我看来,我需要获取当前值,添加一个,然后将其保存在表中,带我到这个代码:

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

Unfortunately, I am unable to get it right, coming up with errors such as: 不幸的是,我无法做到正确,遇到如下错误:

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

Could someone please tell me where I'm going wrong. 有人可以告诉我哪里出错了。

Edit: Update on answer (finally) 编辑:答案更新(最后)

My SQL is: 我的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

And code behind is: 而代码背后是:

 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);
                    }
                }

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

SET @count = UserCount 

is incorrect. 是不正确的。 You can't access columns from previous SELECT statements like that. 您无法像以前那样访问之前SELECT语句中的列。

You can just do it all in one atomic statement. 你可以在一个原子语句中完成所有操作。 This increments the column and sets the output parameter with the new value of UserCount. 这会使列递增,并使用UserCount的新值设置输出参数。

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

This avoids race conditions from reading and writing the value in separate operations. 这避免了竞争条件在单独的操作中读取和写入值。

For reference case, it should be like this 对于参考案例,它应该是这样的

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

But you can just avoid that and do this instead 但你可以避免这种情况,而是这样做

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

Update 更新

Notice I added AND UserCount < @MaxUserCount . 注意我添加了AND UserCount < @MaxUserCount Your stored procedure might not capture all the count as page refreshes quickly [race condition]. 由于页面快速刷新[竞争条件],您的存储过程可能无法捕获所有计数。 You may have an old @Count value. 您可能有一个旧的@Count值。

  • Make sure the count is only increase if MAX is not reached 如果未达到MAX,请确保仅增加计数
  • Just get the count at any point in time with another PROC. 只需在任何时间点与另一个PROC获取计数。 Don't do it in the same PROC as for updating count as you can get OLD count value 不要在与更新计数相同的PROC中执行此操作,因为您可以获得OLD计数值
  • Can have a flag on your table that is SET in the PROC once MAX is reached 达到MAX后,可以在PROC上有一个SET标志

Use below code in your procedure : 在您的程序中使用以下代码:

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

no need to use temporary variables and use of select query. 无需使用临时变量和使用select查询。 try this.. 尝试这个..

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM