Reputation: 595
Suppose I have two tables:
CREATE TABLE Customers
(
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
FullName varchar(100) NOT NULL,
);
CREATE TABLE Employees
(
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
FullName varchar(100) NOT NULL,
);
If I have used the FullName
column of the Customers
table in any stored procedure, then I want to get all those stored procedure names by searching with ColumnName = 'FullName'
and TableName = 'Customers'
.
I don't need those stored procedure names where I have used the FullName
column from the Employees
table.
Is it possible to write a script for this in SQL Server?
NB: In my search criteria I want to search with column name and Table name.
Upvotes: 3
Views: 3157
Reputation: 5131
Due to the dynamic aspect of SQL (links between objects are not always known at the moment of creating the object except in the case of using SCHEMABINDING directive) links are completed when "executing" the object. So the only way to be shure that you will find all objetc with a reference of another object or attribute of an object is to use an internal standard for naming...
Personnaly I use this convention for my business development (actually I do that for clubmed...)... But it is in french !
To summarize:
And so on...
So to find any impact of changing the definition of a column in routines (procs, triggers, functions, view...) the query to run is :
SELECT *
FROM sys.sql_modules
WHERE definition LIKE '%TWN?_ID%' ESCAPE '?'
This will find all object containing a column nammed TWN_ID.
Upvotes: 0
Reputation: 1
The table sys.dm_sql_referenced_entities
will give you the information that you are after. You can check its reference in the Microsoft website: SQL Server 2019 Reference
I like to complete this with a text search. To do this you can export all your Store Procedures scripts as flat files and then you search in the files.
You can use the function "Find in Files" of Notepad++ to find references. You will need to consider that column may have been referred using different formats: ."Date_Id", .[Date_Id] or .Date_Id.
Upvotes: 0
Reputation: 71596
You don't need to use sys.sql_dependencies
which has been deprecated, you can use the newer sys.dm_sql_referenced_entities
instead.
Unfortunately, after some testing, it turns out that
sys.sql_expression_dependencies
andsys.dm_sql_referencing_entities
do not return information on column-level dependencies.
SELECT OBJECT_SCHEMA_NAME(o.object_id),
OBJECT_NAME(o.object_id)
FROM sys.objects o
JOIN sys.schemas s ON s.schema_id = o.schema_id
CROSS APPLY sys.dm_sql_referenced_entities(QUOTENAME(s.name) + '.' + QUOTENAME(o.name), 'OBJECT') d
INNER JOIN sys.columns c
ON c.object_id = d.referenced_id
AND c.column_id = d.referenced_minor_id
AND c.object_id = OBJECT_ID('dbo.Customers')
AND c.name = 'FullName'
WHERE o.type IN ('FN','TF','IF','P','V','TR'); -- scalar, multi-line and inline funcs, procs, views, triggers
Upvotes: 5
Reputation: 453327
sys.sql_dependencies
is deprecated but whilst it is still around you can use
SELECT OBJECT_SCHEMA_NAME(d.object_id),
OBJECT_NAME(d.object_id)
FROM sys.sql_dependencies d
INNER JOIN sys.columns c
ON c.object_id = d.referenced_major_id
AND c.column_id = d.referenced_minor_id
WHERE d.class = 0
AND d.referenced_major_id = object_id('dbo.Customers')
AND c.name = 'FullName'
This has a lot of advantages over a text search in that you won't get issues where procedures contain both the string Customers
and FullName
but as comments or some other context that would yield a false positive. It also handles cases where procedures contain *
rather than mentioning the name explicitly.
If you use dynamic SQL you will likely need to fall back to a more painful text search though.
I'd probably end up using a hybrid approach to cover all angles as below so I can eliminate the need to actually review the text of definite dependencies found in sys.sql_dependencies
and just have to manually review the "Possibles"
WITH Candidates AS
(
SELECT d.object_id, 0 AS Source
FROM sys.sql_dependencies d
INNER JOIN sys.columns c
ON c.object_id = d.referenced_major_id
AND c.column_id = d.referenced_minor_id
WHERE d.class = 0
AND d.referenced_major_id = object_id('dbo.Customers')
AND c.name = 'FullName'
UNION ALL
SELECT m.object_id, 1 AS Source
FROM sys.sql_modules m
WHERE m.definition LIKE '%Customers%' AND (m.definition LIKE '%FullName%' OR m.definition LIKE '%*%')
)
SELECT SchemaName = OBJECT_SCHEMA_NAME(object_id),
ModuleName = OBJECT_NAME(object_id),
Confidence = IIF(MIN(Source) = 0, 'High', 'Possible')
FROM Candidates
GROUP BY object_id
Upvotes: 2