sp_Blitz: include affected foreign key count in “Foreign Keys Not Trusted” details#3912
Conversation
Agent-Logs-Url: https://github.com/BrentOzarULTD/SQL-Server-First-Responder-Kit/sessions/a0acda18-80c1-4d31-a268-7222355e50a9 Co-authored-by: BrentOzar <245462+BrentOzar@users.noreply.github.com>
BrentOzar
left a comment
There was a problem hiding this comment.
Doesn't this query now need a group by since it's got a HAVING and a SUM?
Good catch to ask. In this case, no |
BrentOzar
left a comment
There was a problem hiding this comment.
Looks good! Thanks, Captain Circuits.
There was a problem hiding this comment.
Pull request overview
Updates sp_Blitz CheckID 48 (“Foreign Keys Not Trusted”) to include the number of untrusted foreign keys in the Details message for each affected database.
Changes:
- Switched CheckID 48 output to an aggregate query so it can compute
COUNT(*)of untrusted foreign keys. - Injected the computed FK count into the
Detailsstring. - Added
HAVING COUNT(*) > 0to avoid emitting a row when no untrusted foreign keys exist.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ''Foreign Keys Not Trusted'', | ||
| ''https://www.brentozar.com/go/trust'', | ||
| (''The ['' + DB_NAME() + ''] database has foreign keys that were probably disabled, data was changed, and then the key was enabled again. Simply enabling the key is not enough for the optimizer to use this key - we have to alter the table using the WITH CHECK CHECK CONSTRAINT parameter.'') | ||
| (''The ['' + DB_NAME() + ''] database has '' + CAST(COUNT(*) AS NVARCHAR(20)) + '' foreign keys that were probably disabled, data was changed, and then the key was enabled again. Simply enabling the key is not enough for the optimizer to use this key - we have to alter the table using the WITH CHECK CHECK CONSTRAINT parameter.'') |
There was a problem hiding this comment.
The updated Details string will produce grammatically incorrect output when exactly 1 foreign key is affected ("1 foreign keys"). Consider adding singular/plural handling so the message reads correctly for both 1 and >1.
| (''The ['' + DB_NAME() + ''] database has '' + CAST(COUNT(*) AS NVARCHAR(20)) + '' foreign keys that were probably disabled, data was changed, and then the key was enabled again. Simply enabling the key is not enough for the optimizer to use this key - we have to alter the table using the WITH CHECK CHECK CONSTRAINT parameter.'') | |
| (''The ['' + DB_NAME() + ''] database has '' + CAST(COUNT(*) AS NVARCHAR(20)) + CASE WHEN COUNT(*) = 1 THEN '' foreign key that was probably disabled, data was changed, and then the key was enabled again. Simply enabling the key is not enough for the optimizer to use this key - we have to alter the table using the WITH CHECK CHECK CONSTRAINT parameter.'' ELSE '' foreign keys that were probably disabled, data was changed, and then the key was enabled again. Simply enabling the key is not enough for the optimizer to use this key - we have to alter the table using the WITH CHECK CHECK CONSTRAINT parameter.'' END) |
| ''https://www.brentozar.com/go/trust'', | ||
| (''The ['' + DB_NAME() + ''] database has foreign keys that were probably disabled, data was changed, and then the key was enabled again. Simply enabling the key is not enough for the optimizer to use this key - we have to alter the table using the WITH CHECK CHECK CONSTRAINT parameter.'') | ||
| (''The ['' + DB_NAME() + ''] database has '' + CAST(COUNT(*) AS NVARCHAR(20)) + '' foreign keys that were probably disabled, data was changed, and then the key was enabled again. Simply enabling the key is not enough for the optimizer to use this key - we have to alter the table using the WITH CHECK CHECK CONSTRAINT parameter.'') | ||
| from [?].sys.foreign_keys i INNER JOIN [?].sys.objects o ON i.parent_object_id = o.object_id INNER JOIN [?].sys.schemas s ON o.schema_id = s.schema_id |
There was a problem hiding this comment.
Now that this check aggregates to a single row, the joins to sys.objects and sys.schemas are no longer used for filtering or output. Consider removing the joins and counting directly from sys.foreign_keys to reduce query work and keep the check simpler.
| from [?].sys.foreign_keys i INNER JOIN [?].sys.objects o ON i.parent_object_id = o.object_id INNER JOIN [?].sys.schemas s ON o.schema_id = s.schema_id | |
| from [?].sys.foreign_keys i |
The
sp_Blitz“Foreign Keys Not Trusted” finding (CheckID 48) currently reports only that a database has untrusted foreign keys. This update makes the details message include the number of affected foreign keys in that database.What changed
sp_Blitz.sqlto compute and inject the FK count intoDetails.The [X] database has foreign keys that were...The [X] database has Y foreign keys that were...Query shape adjustment for counted output
SELECT DISTINCT 48to an aggregateSELECT 48withCOUNT(*).HAVING COUNT(*) > 0so rows are emitted only when untrusted FKs exist.Scope
sp_Blitz.sqlwas modified.Install%.sqlscripts were intentionally not edited.