Finding Where Database Fields are Used in Procedures or Functions

This week I needed to quickly determine which database fields are being actively used or displayed within a report.  We’re working with a client to map their source data into the K12 data warehouse model provided by Mariner.  We wanted to cross-reference which fields are actively being used or not, for the purpose of determining how much work we should go to to populate particular fields that are difficult to retrieve or derive.  Because our SSRS reports rely upon stored procedures in SQL Server to perform the queries, I was able to query the system tables.

Query Results

The results of the query shown below are 3 columns:  the table, the column, and the procedure name or function name that uses the column. 

image

Query

The query looks for both stored procedures and functions, since we often utilize functions underneath stored procedures (more info on that here: Using Table Valued Functions to Support SSRS Reporting).

Key components of the query are as follows:

  • The initial table variable returns the object name and the full text (i.e., the create statement).  The full text is what’s searched in the last 2 lines of the where statement.
  • It is within the initial table variable that we specify to only search stored procedures or functions.
  • The final lines of the where statement searches the “ObjectText” from the table variable for the column name within it.  This is where the magic happens (and prevents bad effects from the cross join we had to do).

USE EdDW;

GO 

DECLARE @ObjectUsed TABLE

(  ObjectName NVARCHAR(128)

  ,ObjectText NVARCHAR(MAX)

)

 

INSERT INTO @ObjectUsed

     SELECT DISTINCT

             SysObj.Name

            ,LTRIM(RTRIM(SysComm.[text])) AS [Text]

     FROM [sysobjects] AS SysObj

            INNER JOIN [syscomments] AS SysComm

                   ON SysObj.Id = SysComm.ID

                 AND SysObj.[Type] IN('P','TF','IF','FN')

---------------

SELECT DISTINCT

     SysTbls.name AS [Table Name]

    ,SysCols.name AS [Column Name]

    ,ObjectUsed.ObjectName AS ObjectName

FROM [sys].[tables] AS SysTbls

     LEFT JOIN  [sys].[columns] AS SysCols

                ON  SysTbls.[object_id] = SysCols.[object_id]

     LEFT JOIN  [sys].[objects] as SysObj

                ON  SysTbls.[object_id] = SysObj.[object_id]

     LEFT JOIN [sys].[types] AS SysTyp

                ON  SysCols.user_type_id = SysTyp.[user_type_id]

     CROSS JOIN @ObjectUsed AS ObjectUsed

WHERE SysTbls.name IS NOT NULL

     AND SysCols.name IS NOT NULL

     AND ObjectText LIKE '%' + SysCols.name + '%'

     AND ObjectText LIKE '%' + SysTbls.name + '%'

ORDER BY

     SysTbls.name

    ,SysCols.name