Question

I need a script to check if a given column in a given table is used in any views. Ideally I would like to get the name of the view(s) as well.

I am using T-SQL, and I need to run the script to check this inside an application I am developing.

Was it helpful?

Solution

SQL Server provides a system view, sys.sql_dependencies, which maps the dependencies consumed by objects such as views.

So, to view all the tables and columns associated with the views in your database, use the following query:

;WITH deps
AS
(
    SELECT sd.object_id
        , sd.referenced_major_id
    FROM sys.sql_dependencies sd
    WHERE sd.class = 0
        OR sd.class = 1
    GROUP BY sd.object_id
        , sd.referenced_major_id
)
SELECT ViewName = v.name
    , ReferencedObjectName = o.name
    , ReferencedColumns = STUFF((SELECT N', ' + c.name 
                                 FROM sys.columns c 
                                    INNER JOIN sys.sql_dependencies sd1 ON c.object_id = sd1.referenced_major_id
                                        AND c.column_id = sd1.referenced_minor_id 
                                 WHERE c.object_id = sd.referenced_major_id 
                                 ORDER BY c.object_id FOR XML PATH('')
                                 ), 1, 2, N'')
FROM sys.views v
    INNER JOIN deps sd ON v.object_id = sd.object_id
    INNER JOIN sys.objects o ON sd.referenced_major_id = o.object_id
ORDER BY v.name;

Consider this simple test:

DROP VIEW dbo.my_view_2;
DROP VIEW dbo.my_view;
DROP TABLE dbo.my_table;
DROP TABLE dbo.my_table_2;
CREATE TABLE dbo.my_table (Column_I int NOT NULL, Column_J int NOT NULL);
CREATE TABLE dbo.my_table_2 (Column_J int NOT NULL, Column_K int NOT NULL, Column_L int NOT NULL);
GO
CREATE VIEW dbo.my_view AS SELECT mt.Column_I FROM dbo.my_table mt INNER JOIN dbo.my_table_2 mt2 ON mt.Column_J = mt2.Column_J;
GO
CREATE VIEW dbo.my_view_2 AS SELECT mt.Column_I FROM dbo.my_table mt;
GO

The results of the query above show:

╔═══════════╦══════════════════════╦══════════════════════════════╗
║ ViewName  ║ ReferencedObjectName ║      ReferencedColumns       ║
╠═══════════╬══════════════════════╬══════════════════════════════╣
║ my_view   ║ my_table             ║ Column_I, Column_I, Column_J ║
║ my_view   ║ my_table_2           ║ Column_J                     ║
║ my_view_2 ║ my_table             ║ Column_I, Column_I, Column_J ║
╚═══════════╩══════════════════════╩══════════════════════════════╝

This would limit the output to only views that depend on a specific table:

;WITH deps
AS
(
    SELECT sd.object_id
        , sd.referenced_major_id
    FROM sys.sql_dependencies sd
    WHERE sd.class = 0
        OR sd.class = 1
    GROUP BY sd.object_id
        , sd.referenced_major_id
)
SELECT ViewName = v.name
    , ReferencedObjectName = o.name
    , ReferencedColumns = STUFF((SELECT N', ' + c.name 
                                 FROM sys.columns c 
                                    INNER JOIN sys.sql_dependencies sd1 ON c.object_id = sd1.referenced_major_id
                                        AND c.column_id = sd1.referenced_minor_id 
                                 WHERE c.object_id = sd.referenced_major_id 
                                 ORDER BY c.object_id FOR XML PATH('')
                                 ), 1, 2, N'')
FROM sys.views v
    INNER JOIN deps sd ON v.object_id = sd.object_id
    INNER JOIN sys.objects o ON sd.referenced_major_id = o.object_id
WHERE o.name = N'my_table_1'
ORDER BY v.name;

This could be used to show views that depend on any column in the database with a specific name column_j:

;WITH deps
AS
(
    SELECT sd.object_id
        , sd.referenced_major_id
    FROM sys.sql_dependencies sd
    WHERE sd.class = 0
        OR sd.class = 1
    GROUP BY sd.object_id
        , sd.referenced_major_id
)
SELECT ViewName = v.name
    , ReferencedObjectName = o.name
    , ReferencedColumns = STUFF((SELECT N', ' + c.name 
                                 FROM sys.columns c 
                                    INNER JOIN sys.sql_dependencies sd1 ON c.object_id = sd1.referenced_major_id
                                        AND c.column_id = sd1.referenced_minor_id 
                                 WHERE c.object_id = sd.referenced_major_id 
                                 ORDER BY c.object_id FOR XML PATH('')
                                 ), 1, 2, N'')
FROM sys.views v
    INNER JOIN deps sd ON v.object_id = sd.object_id
    INNER JOIN sys.objects o ON sd.referenced_major_id = o.object_id
WHERE EXISTS (
        SELECT 1 
        FROM sys.columns c 
        WHERE c.object_id = sd.referenced_major_id
        AND c.name = N'Column_J'
        )
ORDER BY v.name;

OTHER TIPS

This is probably helpful for what you're trying to achieve: 4 Ways to Get a View’s Definition using Transact-SQL

Specifically, using Example 4, you can craft a query like this to do what want:

SELECT LEFT(LTRIM(REPLACE(VIEW_DEFINITION, 'CREATE VIEW ', '')), CHARINDEX(' AS', LTRIM(REPLACE(VIEW_DEFINITION, 'CREATE VIEW ', '')))) AS ViewName
FROM INFORMATION_SCHEMA.VIEWS
WHERE VIEW_DEFINITION LIKE '%ColumnName%'

There is a possibility if your column name is a common word, that you get views back that you don't expect though, so you'd have to evolve the query further to account for this if that's your case.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top