Funny you should write an article about this. This is a good topic. I solved this problem in a similar but different way.
We have hundreds of SQL servers in our environment with thousands of changes going in a month. Over time objects become stale and no one really does the due diligence to clean up unused objects. I estimated that we had hundreds of gigabytes of unused tables as well as thousands of unused objects spread across hundreds of production databases.
We also have a mixture of SQL 2000, 2005 and 2008. So this technique had to work on all environments.
(Before reading keep in mind that what my process does is all configurable. You setup what servers and databases you want to monitor)
So I developed an automated process to collect object usage. I first take a snapshot of the target database and store the results in a table. This captures every object in the database and what objects use those objects (it goes through syscomments to find which objects are used by which objects). As someone else pointed out, what happens when a stored procedure calls a stored procedure, or a stored procedure uses a view...etc. This takes care of that concern.
Figuring out what objects use other objects is the easy part. Its figuring out what objects are used by ad-hoc queries that is hard. And for that we have to use a SQL trace.
The process starts a SQL trace to dump trace files out to directory for a given amount of time. Then I use an SSIS package to load trace files into a table and parse through all the SQL being executed against the server. I break apart every "word" in all the SQL and count each word as a potential object name. A stored procedure then executes after this that updates the meta data that was collected in the snapshot step. Keep in mind that this method has a short-coming and that is when you have a table named LA. If anywhere in your code there is a column called LA then its going to assume that the table LA is used. But I wasnt going to spend 6 months writing SQL parsing code. I think its "close enough"
When complete you will have a table that contains all the metadata you need to delete objects that are no longer used.
If you guys want the process let me know and I can email out the SSIS package and database scripts.
Below is the poorly formatted example of the results you will get:
ServerName DatabaseNameObjectNameObjectTypeUsedInProceduresUsedInFunctionsUsedInViewsUsedInTriggersUsedInAdHocQueries
NHQRPTSQL004ATT_WHSEsysconstraintsVNoNoNoNoYes
NHQRPTSQL004ATT_WHSEsyssegmentsVNoNoNoNoNo
NHQRPTSQL004AYS_AsurionCustomersUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionInventoryUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionInvoicesUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionLedgerInvoicesUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionPurchaseOrdersUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionRepairOrdersUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionRODetailsUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionShippingUNoNoNoNoYes
NHQRPTSQL004AYS_AsurionsyssegmentsVNoNoNoNoNo
NHQRPTSQL004AYS_AsurionsysconstraintsVNoNoNoNoYes
NHQRPTSQL004AYS_AsurionMSreplication_subscriptionsUNoNoNoNoYes
This is just the results of a view I wrote. There is enough metadata to drill into exactly what objects use each object 🙂