Hi expert how I can lock a row in sql server that prevent CRUD operation even SELECT. Is it Possible? Serializable Isolation level does not prevent SELECT. thanks
BEGIN TRAN
SELECT 1
FROM Table
WITH (XLOCK, ROWLOCK)
COMMIT TRAN
That will do the trick.
EDIT
As noted by others, you cannot lock a row to not be read. The only way I know of doing this is as follows:
WITH (UPDLOCK, TABLOCK)
And this is assuming that a WITH (NOLOCK) is never used in a SELECT statement (which should be avoided anyway).
I tested this and it will work, although TABLOCK should only be used in extreme cases. Certainly if concurrency is required, it's a bad solution and some other form of locking would be needed. One way is to update a bit column "Available True/False" and only read rows where Available = True. As @gbn suggested, READPAST could be used with this.
It's possible to lock a row using a locking hint WITH (ROWLOCK), however a SELECT statement can always get around it by adding a locking hint WITH (NOLOCK) which will provide a dirty read.
As well as ROWLOCK, XLOCK as suggested by other folk, I would consider READPAST in addition
This allows allows other readers and writers to skip the lock on this row. This can increase concurrency because the lock set by ROWLOCK, XLOCK s blocking otherwise
try using the ROWLOCK
and UPDLOCK
inside a transaction something like this:
BEGIN TRANSACTION
SELECT @ID = ID
FROM YourTable WITH (ROWLOCK, UPDLOCK)
WHERE ....
--more--
COMMIT TRANSACTION
however you can't prevent a SELECT that uses the NOLOCK hint from "dirty" reading this.
SQL Server already natively locks a record from dirty reads as it is being updated. This has the effect of blocking the select call until the update / insert call is complete.