“Pop”记录 - 在同一语句中选择和删除(SQL Server 2005)

时间:2012-03-22 17:27:05

标签: c# sql sql-server-2005

我有一个C#应用程序,大约有十几名员工同时使用它。它只是从SQL Server 2005表中选择顶级记录,删除它,然后在表单上显示数据 一旦选择了记录,就需要删除它,因此2个人不会抓取并处理相同的记录 相当直接......

我刚才发现了一个建议(无法找到我得到的网站,抱歉)在同一个语句中执行SELECT和DELETE并执行 SqlCommand.ExecuteReader()复合“声明:

SELECT TOP 1 * 
FROM Call_Table 
WHERE Call_Table.hold_call_till <= GetDate() 
ORDER BY Call_Table.attempts ASC, Call_Table.custno ASC;
DELETE 
FROM Call_Table
WHERE Call_Table.custno = (SELECT TOP 1 Call_Table.custno 
                           FROM Call_Table 
                           WHERE Call_Table.hold_call_till <= GetDate() 
                           ORDER BY Call_Table.attempts ASC, Call_Table.custno ASC);

到目前为止它一直运作良好,但我觉得我很幸运。我们正在招聘5个新人,我想完全确定这将继续有效。

我很想听听这个领域有更多经验丰富的兽医的意见。

我应该坚持“如果没有破坏,不解决它”的方法?或者我应该加强我的游戏并使用某种record_locks或存储过程?

任何建议都将被公开接受。如有必要,我可以提供有关表或C#应用程序的更多信息。

3 个答案:

答案 0 :(得分:2)

我建议使用某种optimistic concurrency control代替。不要删除记录,而是存储将在select上抓取的时间戳(或其他一些版本控制技术)。然后,如果用户编辑了某些内容,您可以检查以确保时间戳没有更改。如果有,则提示用户并重新加载新数据。如果没有,则保存数据,并更新时间戳,以便其他拥有数据的人不会覆盖您的更改。

Microsoft's article on optimistic concurrency

这是我的图形示例版本(使用编号系统而不是版本控制的时间戳)

Name|PhoneNum|Version
Joe |123-1234|1
  • UserA和UserB在您的用户界面中提取Joe的数据

  • UserA修改并保存Joe

现在表格如下:

Name|PhoneNum|Version
Joe |555-5555|2
  • UserB修改Joe的数据版本1并保存。保存看到版本现在为2,并提示UserB数据已更改。

<强>更新

如果在用户阅读时无法访问该行,则有两个选项。

  • 您可以执行您已经在做的事情,但由于OUTPUT(您已经如上所述),您不需要选择...删除。有了这个,您可以删除并获取值。

代码:

DECLARE @CallInfo TABLE (/*Call_Table Schema*/)

DELETE Call_Table
OUTPUT DELETED.* INTO @CallInfo 
WHERE Call_Table.custno = (SELECT TOP 1 Call_Table.custno 
                       FROM Call_Table 
                       WHERE Call_Table.hold_call_till <= GetDate() 
                       ORDER BY Call_Table.attempts ASC, Call_Table.custno ASC)

--The @CallInfo will have the info that you just deleted, so pass that back to the UI
SELECT * FROM @CallInfo
  • 您可以在选择数据之前添加一个锁定列(使用人员锁定的用户ID)。如果用户崩溃或做了不重置锁定的事情,那么你唯一需要担心的是它。我过去曾使用过这个系统,但如果大多数时候删除数据,复杂性可能不值得。如果您只需更新数据,我发现这更有用。你可以添加逻辑,如果同一个用户试图再次获取数据,那么就让它们,因为它可能是一个崩溃。否则,您需要创建一个解锁系统。

答案 1 :(得分:1)

看起来像你需要的是提示UPDLOCK加上这里描述的READPAST提示 http://www.adathedev.co.uk/2010/03/queue-table-processing-in-sql-server.html

答案 2 :(得分:0)

您可以使用OUTPUT clauseDELETE statement删除行并将其返回到同一语句中,例如:

delete queue output deleted.* where id = (select min(id) from queue)

假设你有一个看起来像这样的表

create table Queue(
    ID bigint identity not null primary key,
    Data varchar(max)
)