list of views that depend on a given table and column
-
11-03-2021 - |
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.
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.