Tree of all dependencies in a SQL Server database - sql-server

I have to maintain an old project without documentation, and there is a database with a lot of tables and functions and stored procedures. I want to build a tree of dependencies between tables and stored procedures, for example, this procedure execs these procedures and uses these tables.
Is there any tool that can help me
If there is not, what is the start point for such algorithms? I mean that I can get source code of all procedures from database, and than parse it for all 'exec #', 'update #', 'insert into #' and so on. And in this case, what is the best way to solve this problem (regex maybe, or some special algorithms...)?

Higarian, your code was very useful to me. I refined it a bit to remove circular dependencies, include table references, and to sort by the ObjectPath.
;with ObjectHierarchy ( Base_Object_Id , Base_Cchema_Id , Base_Object_Name , Base_Object_Type, object_id , Schema_Id , Name , Type_Desc , Level , Obj_Path)
as
( select so.object_id as Base_Object_Id
, so.schema_id as Base_Cchema_Id
, so.name as Base_Object_Name
, so.type_desc as Base_Object_Type
, so.object_id as object_id
, so.schema_id as Schema_Id
, so.name
, so.type_desc
, 0 as Level
, convert ( nvarchar ( 1000 ) , N'/' + so.name ) as Obj_Path
from sys.objects so
left join sys.sql_expression_dependencies ed on ed.referenced_id = so.object_id
left join sys.objects rso on rso.object_id = ed.referencing_id
where rso.type is null
and so.type in ( 'P', 'V', 'IF', 'FN', 'TF' )
union all
select cp.Base_Object_Id as Base_Object_Id
, cp.Base_Cchema_Id
, cp.Base_Object_Name
, cp.Base_Object_Type
, so.object_id as object_id
, so.schema_id as ID_Schema
, so.name
, so.type_desc
, Level + 1 as Level
, convert ( nvarchar ( 1000 ) , cp.Obj_Path + N'/' + so.name ) as Obj_Path
from sys.objects so
inner join sys.sql_expression_dependencies ed on ed.referenced_id = so.object_id
inner join sys.objects rso on rso.object_id = ed.referencing_id
inner join ObjectHierarchy as cp on rso.object_id = cp.object_id and rso.object_id <> so.object_id
where so.type in ( 'P', 'V', 'IF', 'FN', 'TF', 'U')
and ( rso.type is null or rso.type in ( 'P', 'V', 'IF', 'FN', 'TF', 'U' ) )
and cp.Obj_Path not like '%/' + so.name + '/%' ) -- prevent cycles n hierarcy
select Base_Object_Name
, Base_Object_Type
, REPLICATE ( ' ' , Level ) + Name as Indented_Name
, SCHEMA_NAME ( Schema_Id ) + '.' + Name as object_id
, Type_Desc as Object_Type
, Level
, Obj_Path
from ObjectHierarchy as p
order by Obj_Path

Here, The max(level) should solve your problem without needing external tools
;WITH cte ( [ID] ,IDSchema,Nome,Tipo,level, SortCol)
AS (SELECT [so].[object_id] AS ID
,so.[schema_id],so.[name],so.[type]
,0 AS [Level]
,CAST ([so].[object_id] AS VARBINARY (MAX)) AS SortCol
FROM [sys].[objects] so
LEFT JOIN sys.sql_expression_dependencies ed ON [ed].[referenced_id]=[so].[object_id]
LEFT JOIN [sys].[objects] rso ON rso.[object_id]=[ed].referencing_id
--in my database, if i insert tables on the search, it gets more tham 100 levels of recursivity, and that is bad
WHERE [rso].[type] IS NULL AND [so].[type] IN ('V','IF','FN','TF','P')
UNION ALL
SELECT [so].[object_id] AS ID
,so.[schema_id],so.[name],so.[type]
,Level + 1
,CAST (SortCol + CAST ([so].[object_id] AS BINARY (4)) AS VARBINARY (MAX))
FROM [sys].[objects] so
INNER JOIN sys.sql_expression_dependencies ed ON [ed].[referenced_id]=[so].[object_id]
INNER JOIN [sys].[objects] rso ON rso.[object_id]=[ed].referencing_id
INNER JOIN cte AS cp ON rso.[object_id] = [cp].[ID]
WHERE [so].[type] IN ('V','IF','FN','TF','P')
AND ([rso].[type] IS NULL OR [rso].[type] IN ('V','IF','FN','TF','P'))
)
--CTE
SELECT ID, IDSchema,
REPLICATE(' ',level)+nome AS Nome,'['+SCHEMA_NAME(IDSchema)+'].['+nome+']' AS Object,Tipo,Level,SortCol
FROM cte AS p
ORDER BY sortcol

There are paid tools like redgate but if you want, you can always right click an object and select "view dependencies".

You can use sys.dm_sql_referenced_entities as shown below to get all dependencies of any object
SELECT
*
FROM
sys.dm_sql_referenced_entities('dbo.myStoredProcedure', 'OBJECT')

Someone mentioned Redgate's paid add-ons. ApexSQL is another company that makes add-ons for SQL Server. Some of them cost money, but others are free and still pretty useful.
ApexSQL Search is one of the free ones. It's 2 main features are:
Allows you to search a database's data or structure for certain text.
Can build a graphical tree of dependencies for one or more objects (what you want).
After you install it, just right-click an object or database and click View dependencies (near the bottom, with an icon next to it). Don't confuse it for View Dependencies (near the top, without an icon next to it), which is the one built into SQL Server. I find the hierarchical diagram layout to be the most useful.
Links:
Product page with a good video demo
Article about the dependency mapping feature
Download page

Related

Run query for each database in a list and append results

I have the below code to pull the row and column counts from each table within a database (e.g., db1). But I have several databases (e.g., db1, db2 etc.) , so manually updating the database name in the USE statement for every run isn't very convenient. Is there a way to pass a list of database names in a cursor (or something else that allows iteration) and then run the below query for every database in the list, appending the results from each run? I can get the list of database names from this query select name from master.dbo.sysdatabases where name like '%db%'.
USE [db1]
;with [rowCount] as
(
SELECT DB_NAME() as [DB_Name],
QUOTENAME(SCHEMA_NAME(sOBJ.schema_id)) + '.' + QUOTENAME(sOBJ.name) AS [TableName],
SUM(sPTN.Rows) AS [RowCount]
FROM SYS.OBJECTS AS sOBJ
INNER JOIN SYS.PARTITIONS AS sPTN
ON sOBJ.object_id = sPTN.object_id
WHERE
sOBJ.type = 'U'
AND sOBJ.is_ms_shipped = 0x0
AND index_id < 2 -- 0:Heap, 1:Clustered
GROUP BY
sOBJ.schema_id
,sOBJ.name
)
,columnCount as
(
select
QUOTENAME(col.TABLE_SCHEMA) + '.' + QUOTENAME(col.TABLE_NAME) AS [TableName],
count(*) as ColumnCount
from INFORMATION_SCHEMA.COLUMNS col
inner join INFORMATION_SCHEMA.TABLES tbl
on col.TABLE_SCHEMA = tbl.TABLE_SCHEMA
and col.TABLE_NAME = tbl.TABLE_NAME
and tbl.TABLE_TYPE <> 'view'
group by
QUOTENAME(col.TABLE_SCHEMA) + '.' + QUOTENAME(col.TABLE_NAME)
)
select r.[DB_Name], r.TableName, r.[RowCount], c.ColumnCount
from [rowCount] r
inner join columnCount c
on r.TableName = c.TableName
ORDER BY r.[TableName]

Find all dependencies of a list of stored procedures

We have a list of 51 stored procedures used in our application.
I need to find out the names of all the functions and stored procedures called by those stored procs
Is there a quick way to find out what our stored procedures are calling?
I tried using sys.dm_sql_referencing_entities as below
SELECT
referencing_schema_name +'.'+ referencing_entity_name AS ReferencedEntityName,
referencing_class_desc AS ReferencingEntityDescription
FROM sys.dm_sql_referencing_entities ('dbo.sp_GetPayRunDetails', 'OBJECT');
GO
but I am hoping that there is a way to check all 50 stored procs and get detailed information about what other objects (stored procs, and functions) that they call...
I don't want to do this manually is because I also need recursive dependencies for the stored procs and functions that are called...
This query might do the trick for you:
WITH cteDependencies AS (
SELECT e.referencing_id object_id, e.referencing_id, e.referenced_id, e.referenced_schema_name, e.referenced_entity_name
FROM sys.sql_expression_dependencies e
WHERE e.referencing_id = OBJECT_ID('dbo.sp_GetPayRunDetails')
UNION ALL
SELECT d.object_id, e.referencing_id, e.referenced_id, e.referenced_schema_name, e.referenced_entity_name
FROM sys.sql_expression_dependencies e
JOIN cteDependencies d ON d.referenced_id = e.referencing_id AND e.referenced_id <> e.referencing_id
)
SELECT OBJECT_NAME(d.object_id) source_name, d.*
FROM cteDependencies d
JOIN sys.all_objects o ON d.referenced_id = o.object_id
WHERE o.[type] IN ('P','FN','TF'); -- for a list of types see https://msdn.microsoft.com/en-us/library/ms178618.aspx?f=255&MSPPError=-2147217396
Note that it will fail on circular references; if you have such, you need to track the dependency path (for instance in a XML column) and skip items which are repeated.
You can change the "source" by altering the OBJECT_ID('dbo.sp_GetPayRunDetails') filter to include the SPs you want to analyze.
I had a function. Modify it as per your means. It manages self-references
CREATE FUNCTION GetDependents(
#ObjectName AS SYSNAME
)
RETURNS #result TABLE ( Seq INT IDENTITY, ObjectName SYSNAME, Hierarchy VARCHAR(128) , objNameStr varchar(max) )
AS
BEGIN
;WITH Obj AS (
SELECT DISTINCT s.id AS ParentID, s.DepID AS ObjectID, o1.Name AS ParentName, o2.Name AS ChildName,
QUOTENAME(sch1.name) + '.' + QUOTENAME(o1.Name) + '(' + RTRIM(o1.type) + ')' COLLATE SQL_Latin1_General_CP1_CI_AS
AS ParentObject,
QUOTENAME(sch2.name) + '.' + QUOTENAME(o2.Name) + '(' + RTRIM(o2.type) + ')' COLLATE SQL_Latin1_General_CP1_CI_AS AS ObjectName,
o2.Name as objNameStr
FROM sys.sysdepends s
INNER JOIN sys.all_objects o1 ON s.id = o1.object_id
INNER JOIN sys.schemas sch1 ON sch1.schema_id = o1.schema_id
INNER JOIN sys.all_objects o2 on s.DepID = o2.object_id
INNER JOIN sys.schemas sch2 ON sch2.schema_id = o2.schema_id
where o2.type not in ('u') and s.id <>s.DepID --Self Reference ko hata...
), cte AS (
SELECT
0 AS lvl,
ParentID,
ObjectId,
ParentObject,
ObjectName,
CAST(ObjectID AS VARBINARY(512)) AS Sort
, objNameStr
FROM obj WHERE ParentName = #ObjectName
UNION ALL
SELECT
p.lvl+ 1,
c.ParentID,
c.ObjectId,
c.ParentObject,
c.ObjectName,
CAST(p.sort + CAST(c.ObjectID AS VARBINARY(16))
AS VARBINARY(512)), c.objNameStr
FROM cte p
INNER JOIN obj c ON p.ObjectID = c.ParentID
)
INSERT INTO #result (ObjectName, Hierarchy,objNameStr)
SELECT
ObjectName,
'|-' + REPLICATE('-',(lvl * 4)) + ObjectName,
objNameStr
FROM cte
ORDER BY Sort
OPTION (MAXRECURSION 32767);
RETURN
END

Query to Recursively Identify Object Dependencies

I have a complex query with several tables, views and functions within it. The functions and views split off into more views and functions that potentially split off into more views and functions within them.
This query is having performance issues so I want to get a clear and concise list of all the objects that are being referenced within my query so I have a basis for my investigation. How do I get this list of objects?
DESCRIPTION
Wrote this Stored Procedure below which RECURSIVELY lists all the dependent child objects and child's dependent objects and child's child...etc. The input parameter can be Stored Proc, User Function, View.
Can easily be altered to get a Unique List of Column 5, regardless of what Level the Object was called and how deep and by which object.
COLUMNS
UsedByObjectId - The parent object that uses the dependent object
UsedByObjectName - The name of the parent object
UsedByObjectType - Type of the parent object (P,V,FN)
DependentObjectId - The child object the parent uses
DependentObjectName - Name of the child object
DependentObjectType - Type of the dependent child object (P,V,FN, U)
Level - How deep, the nested recursive level which the object is used
THE CODE
--=========================================================================
--=========================================================================
--== utlGetAllDependentObjectsRecursive - Uses recursive common table
--== expression to recursively get all the dependent objects as well
--== as the child objects and child's child objects of a
--== Stored Procedure or View or Function. can be easily modified to
--== include all other types of Objects
--=========================================================================
--=========================================================================
CREATE PROCEDURE utlGetAllDependentObjectsRecursive
(
-- Supports Stored Proc, View, User Function, User Table
#PARAM_OBJECT_NAME VARCHAR(500)
)
AS
BEGIN
WITH CTE_DependentObjects AS
(
SELECT DISTINCT
b.object_id AS UsedByObjectId,
b.name AS UsedByObjectName, b.type AS UsedByObjectType,
c.object_id AS DependentObjectId,
c.name AS DependentObjectName , c.type AS DependenObjectType
FROM sys.sysdepends a
INNER JOIN sys.objects b ON a.id = b.object_id
INNER JOIN sys.objects c ON a.depid = c.object_id
WHERE b.type IN ('P','V', 'FN') AND c.type IN ('U', 'P', 'V', 'FN')
),
CTE_DependentObjects2 AS
(
SELECT
UsedByObjectId, UsedByObjectName, UsedByObjectType,
DependentObjectId, DependentObjectName, DependenObjectType,
1 AS Level
FROM CTE_DependentObjects a
WHERE a.UsedByObjectName = #PARAM_OBJECT_NAME
UNION ALL
SELECT
a.UsedByObjectId, a.UsedByObjectName, a.UsedByObjectType,
a.DependentObjectId, a.DependentObjectName, a.DependenObjectType,
(b.Level + 1) AS Level
FROM CTE_DependentObjects a
INNER JOIN CTE_DependentObjects2 b
ON a.UsedByObjectName = b.DependentObjectName
)
SELECT DISTINCT * FROM CTE_DependentObjects2
ORDER BY Level, DependentObjectName
END
I saw this post to identify all the objects that reference a particular synonym and used the base logic in the answer in a recursive CTE to identify all the objects related to a comma-delimited list of the objects within the top level query being executed.
Declare #baseObjects Nvarchar(1000) = '[Schema].[Table],[Schema].[View],[Schema].[Function],[Schema].[StoredProc]',
#SQL Nvarchar(Max);
Declare #objects Table (SchemaName Varchar(512), TableName Varchar(512), ID Int, xtype Varchar(10));
Set #SQL = 'Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From sysobjects so
Join sys.schemas ss
On so.uid = ss.schema_id
Where so.id In (Object_ID(''' + Replace(#baseObjects,',','''),Object_ID(''') + '''))';
Insert #objects
Exec sp_executeSQL #SQL;
With test As
(
Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From sys.sql_expression_dependencies sed
Join #objects vo
On sed.referencing_id = vo.ID
Join sysobjects so
On sed.referenced_id = so.id
Join sys.schemas ss
On so.uid = ss.schema_id
Union All
Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From test
Join sys.sql_expression_dependencies sed
On sed.referencing_id = test.id
And sed.referencing_id <> sed.referenced_id
Join sysobjects so
On sed. referenced_id = so.id
Join sys.schemas ss
On so.uid = ss.schema_id
)
Select Distinct *
From test
Union
Select *
From #objects;
Check This one, You will get all recursive objects.
WITH Refobjects
(referencing_object_name,referencing_object_type_desc)
AS
(
SELECT
o.name AS referencing_object_name,
o.type_desc AS referencing_object_type_desc
FROM
sys.sql_expression_dependencies sed
INNER JOIN
sys.objects o ON sed.referencing_id = o.[object_id]
WHERE
sed.referenced_entity_name = 'Your Object Name'
UNION ALL
SELECT
o.name AS referencing_object_name,
o.type_desc AS referencing_object_type_desc
FROM
sys.sql_expression_dependencies sed
INNER JOIN
sys.objects o ON sed.referencing_id = o.[object_id]
INNER JOIN Refobjects ON sed.referenced_entity_name = Refobjects.referencing_object_name
)
SELECT distinct * FROM Refobjects
Order by 2 desc,1 ;
In SQL Server 2008 there are two new Dynamic Management Functions introduced to keep track of object dependencies: sys.dm_sql_referenced_entities and sys.dm_sql_referencing_entities:
1/ Returning the entities that refer to a given entity:
SELECT
referencing_schema_name, referencing_entity_name,
referencing_class_desc, is_caller_dependent
FROM sys.dm_sql_referencing_entities ('<TableName>', 'OBJECT')
2/ Returning entities that are referenced by an object:
SELECT
referenced_schema_name, referenced_entity_name, referenced_minor_name,
referenced_class_desc, is_caller_dependent, is_ambiguous
FROM sys.dm_sql_referenced_entities ('<StoredProcedureName>', 'OBJECT');
Another option is to use a pretty useful tool called SQL Dependency Tracker from Red Gate.
Based on #Raju Chavan's answer above, which works great. However...
I've added support for schemas, as well as returning (and ordering by) the recursion level, so one can easily turn it into a script to refresh referencing objects in the correct order, using sp_refreshsqlmodule (see point 3 below).
WITH
cRefobjects AS (
SELECT o.name, s.name AS sch, o.type_desc, 1 AS level
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
WHERE (sed.referenced_schema_name = '<your schema>' OR sed.referenced_schema_name IS NULL)
AND sed.referenced_entity_name = '<your object name>'
UNION ALL
SELECT o.name, s.name AS sch, o.type_desc, cRefobjects.level + 1 AS level
FROM
sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN cRefobjects ON sed.referenced_entity_name = cRefobjects.name
AND sed.referenced_schema_name = cRefobjects.sch
)
SELECT DISTINCT name, sch, type_desc, level
FROM cRefobjects
ORDER BY level, type_desc DESC, name;
A few things to consider:
Replace <your schema> and <your object> with with what you require.
When the referenced object does not have a schema prefix in the referencing object, the schema is actually unknown, hence the predicate above OR sed.referenced_schema_name IS NULL. This may get the wrong referencing object if you're not following best practices in your database objects.
My goal in seeking and finding this answer was to write a script to refresh referenced objects in the database automatically after editing a view, using sp_refreshsqlmodule. To do this, just wrap the CTE shown above as follows. This prints the required SQL for refreshing the referencing objects in the correct order:
DECLARE #SQL NVARCHAR(4000); SET #SQL = '';
WITH
cRefobjects AS (
...
)
--SELECT DISTINCT name, sch, type_desc, level
SELECT #SQL = #SQL + 'EXEC sys.sp_refreshsqlmodule ''' + sch + '.' + name + '''' + CHAR(13)+CHAR(10)
FROM cRefobjects
ORDER BY level, type_desc DESC, name;
PRINT #SQL
I have improved above answers as none was working for me.
I needed a way to refresh complex nested objects by type sp_refreshsqlmodule.
You need to update and <TYPE_NAME> to your own.
Following method work for me:
WITH cRefobjects AS (
SELECT o.name, s.name AS sch, o.type, 1 AS level
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
WHERE (sed.referenced_schema_name = '<SCHEMA>' OR sed.referenced_schema_name IS NULL)
AND sed.referenced_entity_name = '<TYPE_NAME>'
UNION ALL
SELECT o.name, s.name AS sch, o.type, cRefobjects.level + 1 AS level
FROM
sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN cRefobjects ON sed.referenced_entity_name = cRefobjects.name
AND sed.referenced_schema_name = cRefobjects.sch
)
SELECT name, MAX(level) as level, 'EXEC sys.sp_refreshsqlmodule #name = ''' + sch + '.' + name + '''', type
FROM cRefobjects
GROUP BY name, sch, type
ORDER BY level, type, name;

How to get the name of the Parent Table with the help of Column name in Sys.Columns

I wanted to get the table name. I have the column name and when I try to look up at the Sys.Columns table I get the matching name of the column. How will I get the table name to which the required column is associated
SELECT OBJECT_SCHEMA_NAME(object_id) AS TableSchemaName,
OBJECT_NAME(object_id) AS TableName
FROM sys.columns
WHERE name = 'YourColumnName'
I hope this helps:
select t.name from sys.columns c
inner join sys.tables t
on c.object_id = t.object_id
where c.name = 'insert column name here'
select OBJECT_NAME(object_id) as TableName from sys.Columns where name='columnNamehere'
Try this
declare #columnName As varchar(50) = 'ParentColumnName'
select t.name from sys.tables t
join sys.columns c
on c.object_id = t.object_id
and c.name = #columnName
select name as 'TableName' from sys.tables where object_id=
(select object_id from sys.columns where name='UserName')
I know that this is an old question, but the answers listed to date do not get at what the parent table name is for a view's columns, nor if a column is aliased to have a new name with respect to the column name in the parent table.
Unfortunately, (at least in 2008R2) it seems that even with registering your Views to a Schema, the referencing_minor_id of sys.dm_sql_referenced_entities (or the equivalent column from sys.SQL_Modules) is always set to zero. However, you can retrieve all referred-to tables (and parent views), along with which fields of those tables are queried with sys.dm_sql_referenced_entities (or sys.SQL_Modules). However, it does not capture the oorder of those bindings, so the following won't quite work to link view columns directly to table columns, but it'll provide an approximation:
DECLARE #obj_name nvarchar(50) = 'Table_or_View_name_here';
with obj_id as (
select object_id, name, OBJECT_SCHEMA_NAME(object_id)+'.'+name as qualified_name from sys.all_objects as o
where o.name = #obj_name
),
tv_columns as ( -- table or view
select o.name as Obj_Name, c.* from sys.columns as c join
obj_id as o on
c.object_id=o.object_id
),
sql_referenced_entities as (
SELECT
o.name as referencing_name,
o.object_id,
COALESCE(NULLIF(referencing_minor_id,0),ROW_NUMBER() OVER (ORDER BY (select 'NO_SORT'))) as referencing_minor_id,
referenced_server_name,
referenced_database_name,
referenced_schema_name,
referenced_entity_name,
referenced_minor_name,
referenced_id,
referenced_minor_id,
referenced_class,
referenced_class_desc,
is_caller_dependent,
is_ambiguous
FROM obj_id as o, sys.dm_sql_referenced_entities((select qualified_name from obj_id), 'OBJECT') where referenced_minor_id<>0
)
select
c.object_id as object_id,
o.name as object_name,
c.column_id,
c.name as column_name,
c2.object_id as parent_table_object_id,
o2.name as parent_table_name,
c2.column_id as parent_column_id,
c2.name as parent_column_name
-- ,c.*,
-- ,c2.*
from sys.columns as c join
obj_id as o on
c.object_id=o.object_id left outer join
(sql_referenced_entities as s join
sys.all_objects as o2 on
s.referenced_id=o2.object_id and s.referenced_class=1 join
sys.columns as c2 on
s.referenced_id=c2.object_id and s.referenced_minor_id=c2.column_id
) on
c.object_id=s.object_id and c.column_id=s.referencing_minor_id
To get the true aliases used, as well as any calculations involving the combinations of multiple fields, you would have to parse the output of either OBJECT_DEFINITION(OBJECT_ID('schema.view')) (or potentially exec sp_helptext 'schema.view'), as follows
Starting with OBJECT_DEFINITION(OBJECT_ID('schema.view'))
Mark what is enclosed in single quotes as superseeding the removal and other rules to follow
Remove blocks between /* */ comments
Remove any text after --, up to the next linebreak sequence (see EXEC SP_HELPTEXT 'sp_helptext' for their end-of-line code)
Look up table/subselect aliases from the FROM clause
Parse out the SELECT clause and break on commas, rather than end-of-line.
Reduce any contiguous whitespace to a single space character. Force whitespace before [ and after ] when a dot/period (or whitespace) don't already appear.
We'll put the above into a stored procedure that we'll call usp_helptext_for_view
See which table_alias.field_name are aliased or simply appear as field_name. See the below code snippet to see how to seperate the field alias from the definition.
Link the view to the table as appropriate.
drop table #s
create table #s (id bigint identity(1,1) primary key, text nvarchar(max))
insert into #s (text) exec usp_helptext_for_view #qualified_viewname
with s as (select
id,
text,
az=(select
MIN(x*(case x when 0 then null else 1 end)) FROM (VALUES
(charindex(#viewfieldname,text COLLATE Latin1_General_CI_AS)),
(charindex('['+#viewfieldname+']',text COLLATE Latin1_General_CI_AS)),
(charindex('AS ['+#viewfieldname+']',text COLLATE Latin1_General_CI_AS)),
(charindex('as '+#viewfieldname,text COLLATE Latin1_General_CI_AS))
) AS value(x)
),
NULLIF(charindex('=',text),0)) as eq --oh, the irony of how the two different styles are applied
FROM #s
)
SELECT
#viewfieldname as ViewField,
CASE eq WHEN NULL
THEN IIF(az IS NULL, NULL, LEFT(text, az-2))
ELSE RIGHT(text,LENGTH(text)-eq) -- alternately ELSE CASE az WHEN NULL THEN NULL WHEN <eq THEN RIGHT(text,LENGTH(text)-eq) ELSE NULL END
END as ViewFieldDefinition,
id as sortPosition
FROM s
WHERE text like '%'+#viewfieldname+'%' -- you should be able to eliminate this clause without affecting the results.
ORDER BY id, #viewfieldname

Is it possible to list all foreign keys in a database?

How do I list all FK's in a sqlserver database?
I use this statement, it seems to work pretty well.
SELECT RC.CONSTRAINT_NAME FK_Name
, KF.TABLE_SCHEMA FK_Schema
, KF.TABLE_NAME FK_Table
, KF.COLUMN_NAME FK_Column
, RC.UNIQUE_CONSTRAINT_NAME PK_Name
, KP.TABLE_SCHEMA PK_Schema
, KP.TABLE_NAME PK_Table
, KP.COLUMN_NAME PK_Column
, RC.MATCH_OPTION MatchOption
, RC.UPDATE_RULE UpdateRule
, RC.DELETE_RULE DeleteRule
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KF ON RC.CONSTRAINT_NAME = KF.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KP ON RC.UNIQUE_CONSTRAINT_NAME = KP.CONSTRAINT_NAME
Theoretically, this is hard. The relational model allows any field to relate to any other field. Which ones are actually used is defined by all possible SELECT statements that could be used.
Practically, it depends on how many tables have the FK definitions included. If someone bothered to carefully define all FK references -- and the SELECT statements stick to these rules -- you can query them.
However, since a SELECT statement can join on anything, there's no guarantee that you have all FK's unless you also have all SELECT statements.
Edit.
See http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/11/26/viewing-all-foreign-key-constraints-in-sql-server.aspx
SELECT f.name AS ForeignKey,
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
Might work for you.
I use http://technet.microsoft.com/en-us/library/ms189807.aspx
SELECT * FROM sys.foreign_keys
That is if you are on at least SQL Server 2005+ and want to see a list of the FK names.
But you probably want to know more about the tables that are related too, don't you, that is where the answer comes in handy.
Here is a more informative way of presenting it
SELECT DISTINCT PARENT_TABLE =
RIGHT(Replace(TC.constraint_name, 'FK_', ''),
Len(Replace(TC.constraint_name, 'FK_', '')) - Charindex('_', Replace(TC.constraint_name, 'FK_', ''))),
CHILD_TABLE = TC.table_name,
CU.column_name,
TC.constraint_name,
TC.constraint_type
FROM information_schema.table_constraints TC
INNER JOIN information_schema.constraint_column_usage CU
ON TC.constraint_name = CU.constraint_name
WHERE TC.constraint_type LIKE '%foreign'
OR TC.constraint_type LIKE '%foreign%'
OR TC.constraint_type LIKE 'foreign%'
select * from sys.objects where type = 'F'

Resources