I seem to be missing something wrt locks in SQL Server 2008. This is my scenario:
- Begin tran.
- Read from table A to ensure a particular row is found.
- While reading, place a read-only lock on the single row read. If not found, throw error.
- Insert into table B, which includes a reference to table A.
- Commit the tran (releasing the lock).
Due to various design constraints, in this particular instance I cannot create a relationship to manage this for me. So I have to do it with code.
I don't want to XLOCK or UPDLOCK table A as the transaction I am in is only reading from it, not writing. However, obviously I don't want anything else to update / delete the referenced row either. So I need a read-only lock from an external perspective.
I don't want any phantom reads to be possible. I don't want different row versions to be possible, obviously.
Once the tran has committed, it's fine for table A to be modified because a trigger (after delete) will null the reference in table B.
This is what I have:
BEGIN TRAN -- test IF NOT EXISTS ( SELECT 1 FROM Table1 WITH (HOLDLOCK, ROWLOCK) WHERE (ID = @ID) ) {throw} {perform insert into Table2} COMMIT TRAN