sql-servert-sqlnolock

Using NOLOCK on a table which is being joined to itself


I'm working with an awful view which internally joins many, many tables together, some of which are the same table.

I'm wondering, when a table is being joined to itself, how is the NOLOCK hint interpreted if it's on one of the joins and not the other? Is the NOLOCK still in effect on the table, or is the table locked altogether if NOLOCK is not included on one of the joins of the same table?

For example (this is pseduo-code, assume that there are valid JOIN ON conditions):

SELECT *
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK)
JOIN Table2_Table2 tt (NOLOCK)
JOIN Table2 t22 (NOLOCK)
JOIN Table1 t11

Does Table1 get locked or stay NOLOCKed?


Solution

  • Yes it does get locked by the last Table1 t11 call. Each table locking hint is applied to the specific reference. If you apply it to only one of the table references that is only for that reference and the others will have their own individual locking settings. You can test this using BEGIN TRANSACTION and execute two different queries.

    Query 1 (locks the table) Intentionally commenting out the COMMIT TRANSACTION

    BEGIN TRANSACTION
    SELECT *
    FROM Table1 WITH (TABLOCK)
    -- COMMIT TRANSACTION
    

    Since COMMIT TRANSACTION was commented out, the transaction is not closed and will still hold the lock. When the second query is run the first lock will still apply on the table from the first query.

    Query 2 (this query will hang because of the first lock will block on Table1 t11)

    BEGIN TRANSACTION
    SELECT *
    FROM Table1 t1 (NOLOCK)
    JOIN Table2 t2 (NOLOCK)
    JOIN Table2_Table2 tt (NOLOCK)
    JOIN Table2 t22 (NOLOCK)
    JOIN Table1 t11
    COMMIT TRANSACTION