If it is unlikely that inactive lines that are not connected will be linked, you can run (or even dynamically build the foreign key metadata):
SELECT k.* FROM k WITH(NOLOCK) WHERE k.Active = 0 AND NOT EXISTS (SELECT * FROM f_1 WITH(NOLOCK) WHERE f_1.fk = k.pk) AND NOT EXISTS (SELECT * FROM f_2 WITH(NOLOCK) WHERE f_2.fk = k.pk) ... AND NOT EXISTS (SELECT * FROM f_n WITH(NOLOCK) WHERE f_n.fk = k.pk)
And you can easily turn it into a DELETE. But many locks can be stored in a large delete, so you can put this in a table and then delete it in batches - the package should not be interrupted if the record was not connected.
For this to be effective, you really need to have indexes in the FK columns in the related tables.
You can also do this with left-handed connections, but then you (sometimes) have to de-cheat with DISTINCT or GROUP BY, and the execution plan is actually no better, and this does not contribute to code generation:
SELECT k.* FROM k WITH(NOLOCK) LEFT JOIN f_1 WITH(NOLOCK) ON f_1.fk = k.pk LEFT JOIN f_2 WITH(NOLOCK) ON f_2.fk = k.pk ... LEFT JOIN f_n WITH(NOLOCK) ON f_n.fk = k.pk WHERE k.Active = 0 AND f_1.fk IS NULL AND f_2.fk IS NULL ... AND f_n.fk IS NULL
source share