Can I Select and Update at the same time?

后端 未结 6 1620
梦谈多话
梦谈多话 2021-01-19 00:07

This is an over-simplified explanation of what I\'m working on.
I have a table with status column. Multiple instances of the application will pull the contents of the f

相关标签:
6条回答
  • 2021-01-19 00:18

    You should do three things here:

    1. Lock the row you're working on
    2. Make sure that this and only this row is locked
    3. Do not wait for the locked records: skip the the next ones instead.

    To do this, you just issue this:

    SELECT  TOP 1 *
    FROM    mytable (ROWLOCK, UPDLOCK, READPAST)
    WHERE   status = 'NEW'
    ORDER BY
            date
    
    UPDATE  …
    

    within a transaction.

    0 讨论(0)
  • 2021-01-19 00:18

    A stored procedure is the way to go. You need to look at transactions. Sql server was born for this kind of thing.

    0 讨论(0)
  • 2021-01-19 00:20

    You could use the OUTPUT statement.

    DECLARE @Table TABLE (ID INTEGER, Status VARCHAR(32))
    INSERT INTO @Table VALUES (1, 'New')
    INSERT INTO @Table VALUES (2, 'New')
    INSERT INTO @Table VALUES (3, 'Working')
    
    UPDATE  @Table
    SET     Status = 'Working'
    OUTPUT  Inserted.*
    FROM    @Table t1
            INNER JOIN (
              SELECT  TOP 1 ID 
              FROM    @Table
              WHERE   Status = 'New'
            ) t2 ON t2.ID = t1.ID
    
    0 讨论(0)
  • 2021-01-19 00:29

    Not quite, but you can SELECT ... WITH (UPDLOCK), then UPDATE.. subsequently. This is as good as an atomic operation as it tells the database that you are about to update what you previously selected, so it can lock those rows, preventing collisions with other clients. Under Oracle and some other database (MySQL I think) the syntax is SELECT ... FOR UPDATE.

    Note: I think you'll need to ensure the two statements happen within a transaction for it to work.

    0 讨论(0)
  • 2021-01-19 00:30

    Sounds like a queue processing scenario, whereby you want one process only to pick up a given record.

    If that is the case, have a look at the answer I provided earlier today which describes how to implement this logic using a transaction in conjunction with UPDLOCK and READPAST table hints: Row locks - manually using them

    Best wrapped up in sproc.

    I'm not sure this is what you are wanting to do, hence I haven't voted to close as duplicate.

    0 讨论(0)
  • 2021-01-19 00:37

    Yes, and maybe use the rowlock hint to keep it isolated from the other threads, eg.

    UPDATE
    Jobs WITH (ROWLOCK, UPDLOCK, READPAST)
    SET Status = 'WORKING'
    WHERE JobID =
    (SELECT Top 1 JobId FROM Jobs WHERE Status = 'NEW')
    

    EDIT: Rowlock would be better as suggested by Quassnoi, but the same idea applies to do the update in one query.

    0 讨论(0)
提交回复
热议问题