[英]“Pop” Record — Select And Delete In The Same Statement (SQL Server 2005)
I have a C# application that is used by about a dozen employees simultaneously. 我有一个C#应用程序,大约有十几个员工同时使用它。 It simply SELECTs the top record from a SQL Server 2005 table, DELETE it, then displays the data on a form.
它只是从SQL Server 2005表中选择顶级记录,删除它,然后在表单上显示数据。
As soon as the record is selected it needs to be deleted so 2 ppl don't grab and work on the same record. 一旦选择了记录,就需要将其删除,因此2个人不会抓取并处理同一记录。
Fairly Straight Forward... 非常坦率的...
I found a suggestion a while ago (cant find the site i got it from, sorry) to do a SELECT and DELETE in the same statement and execute a SqlCommand.ExecuteReader() with this "compound" statement: 我刚才发现了一个建议(无法找到我得到它的网站,抱歉)在同一个语句中执行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);
Its been working quite well so far, but i feel like i've just been lucky. 到目前为止它一直运作良好,但我觉得我很幸运。 We're hiring about 5 new ppl, and i would like to totally sure this will continue to work.
我们正在招聘5个新人,我想完全确定这将继续有效。
Im interested to hear the opinion of more seasoned vets in this area. 我很想听听这个地区更多经验丰富的兽医的意见。
Should I stick with the "If its not broken, dont fix it" approach?? 我应该坚持“如果没有破坏,不解决它”的方法? Or should I step up my game and use some kind of record_locks or stored procs??
或者我应该加强我的游戏并使用某种record_locks或存储过程?
Any suggestions will be openly accepted. 任何建议都将被公开接受。 I can supply more info about the table or C# application if necessary.
如有必要,我可以提供有关表或C#应用程序的更多信息。
I would suggest using some sort of optimistic concurrency control instead. 我建议使用某种乐观的并发控制 。 Do not delete the record, but instead store a timestamp (or some other versioning technique) which will be grabbed on select.
不要删除记录,而是存储将在select上抓取的时间戳(或其他一些版本控制技术)。 Then, if the user edits something you can check to make sure the timestamp has not changed.
然后,如果用户编辑了某些内容,您可以检查以确保时间戳没有更改。 If it has, then prompt the user and reload the new data.
如果有,则提示用户并重新加载新数据。 If it has not, then save the data, and update the timestamp so that anybody else with the data will not overwrite your changes.
如果没有,则保存数据并更新时间戳,以便其他拥有数据的人不会覆盖您的更改。
Microsoft's article on optimistic concurrency 微软关于乐观并发的文章
Here is my version of a graphical example (using a numbering system instead of timestamps for the versioning) 这是我的版本的图形示例(使用编号系统而不是版本控制的时间戳)
Name|PhoneNum|Version
Joe |123-1234|1
UserA and UserB pull up Joe's data in your UI UserA和UserB在您的UI中提取Joe的数据
UserA modifies and saves Joe UserA修改并保存Joe
Now the table looks like this: 现在表格看起来像这样:
Name|PhoneNum|Version
Joe |555-5555|2
UPDATE UPDATE
You have two options if the row cannot be accessed while the User is reading it. 如果在用户正在读取行时无法访问该行,则有两个选项。
Code: 码:
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
看起来像你需要的是暗示UPDLOCK加上这里描述的READPAST提示http://www.adathedev.co.uk/2010/03/queue-table-processing-in-sql-server.html
You can use the OUTPUT clause of the DELETE statement to delete a row and return it in the same statement, eg: 您可以使用DELETE语句的OUTPUT子句删除行并在同一语句中返回它,例如:
delete queue output deleted.* where id = (select min(id) from queue)
Assuming you have a table that looks something like this 假设你有一个看起来像这样的表
create table Queue(
ID bigint identity not null primary key,
Data varchar(max)
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.