开发者

Find table name in all objects of all databases

开发者 https://www.devze.com 2023-03-31 23:15 出处:网络
I have a system with multiple databases and client applications. All databases are at one SQL Server instance. They have been developed by different people at different time. So if some error occur it

I have a system with multiple databases and client applications. All databases are at one SQL Server instance. They have been developed by different people at different time. So if some error occur it is pritty hard to find in which procedure or trigger the data was modified.

Now I use this script, which I found on this site:

SELECT  DISTINCT ISNULL(sd.referenced_schema_name+'.','')+ OBJECT_NAME(sd.referenced_id)TableName,
        OBJECT_NAME(sd.referencing_id)Ref_Object,
        CASE WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsUserTable')= 1
                     THEN'Table'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsTableFunction')= 1
                     THEN'Function'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsTableFunction')= 1
                     THEN'Function'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsScalarFunction')=1
                     THEN'Function'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsTrigger')= 1
                     THEN'Trigger'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsView')= 1
                     THEN'View'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsUserTable')= 1
                     THEN'Table'
        WHEN OBJECTPROPERTYEX(sd.referen开发者_高级运维cing_id,N'IsProcedure')= 1
                     THEN'Procedure'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsIndexed')= 1
                     THEN'Index'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsForeignKey')= 1
                     THEN'ForeignKey'
        WHEN OBJECTPROPERTYEX(sd.referencing_id,N'IsPrimaryKey')= 1
                     THEN'PrimaryKey'
        END AS Ref_Object_Name
FROM    sys.sql_expression_dependencies SD
        INNER JOIN sys.objects obj
                     ON obj.object_id=sd.referenced_id
WHERE   obj.is_ms_shipped= 0
        and referenced_id=object_id('TABLE_NAME') /*Where one can Replace table Name*/
        AND obj.type_desc='USER_TABLE'
        ORDER BY TableName,Ref_Object,Ref_Object_Name

But this script seems to work only for the database to which the table belong.

I want to get for a specified table name (or even better for an object) list of all objects of all databases in which the specified table name met:

Database_Name  SchemaName  ObjectName  ObjectKind  

Thanks.


DECLARE @table_name SYSNAME = N'%';



DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += 'SELECT DISTINCT Database_Name = ''' + QUOTENAME(name) + ''',
        COALESCE(sd.referenced_schema_name +''.'', '''')+ o.name AS TableName,
        r.name AS Ref_Object,
        r.type_desc AS Ref_Object_Name
FROM    ' + QUOTENAME(name) + '.sys.sql_expression_dependencies AS sd
        INNER JOIN ' + QUOTENAME(name) + '.sys.objects AS o
        ON o.object_id = sd.referenced_id
        INNER JOIN ' + QUOTENAME(name) + '.sys.objects AS r
        ON sd.referencing_id = r.object_id
WHERE   o.is_ms_shipped =  0
        and referenced_id = o.object_id
        AND o.type_desc = ''USER_TABLE''
        AND o.name LIKE ''' + @table_name + '''
UNION ALL
'
 FROM sys.databases 
 WHERE database_id BETWEEN 5 AND 32766;

SET @sql = LEFT(@sql, LEN(@sql)-11) 
    + 'ORDER BY Database_Name, TableName,Ref_Object,Ref_Object_Name';

EXEC sp_executesql @sql;

EDIT

The above will find all the references within each database, but won't find cross-database references. It took a little playing, and the output isn't precisely what you wanted, but I think it makes it more self-explanatory:

DECLARE @table_name SYSNAME = N'%'; -- find all



CREATE TABLE #d
(
    db SYSNAME, 
    [object_id] INT, 
    sch SYSNAME,
    obj SYSNAME,
    ref_db NVARCHAR(128),
    ref_sch NVARCHAR(128), 
    ref_obj NVARCHAR(128),
    ref_object_id INT,
    type_desc SYSNAME
);

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += 'SELECT ''' + QUOTENAME(name) + ''',
    d.referencing_id,
    QUOTENAME(s.name),
    QUOTENAME(o.name),
    QUOTENAME(d.referenced_database_name),
    QUOTENAME(d.referenced_schema_name),
    QUOTENAME(d.referenced_entity_name),
    d.referenced_id,
    o.type_desc
FROM ' + QUOTENAME(name) 
    + '.sys.sql_expression_dependencies AS d
INNER JOIN ' + QUOTENAME(name) 
    + '.sys.objects AS o
    ON d.referencing_id = o.[object_id]
INNER JOIN ' 
    + QUOTENAME(name) + '.sys.schemas AS s
    ON o.[schema_id] = s.[schema_id]
WHERE d.referenced_entity_name LIKE ''' + @table_name + '''
UNION ALL
'
FROM sys.databases WHERE database_id BETWEEN 5 AND 32766;

SET @sql = LEFT(@sql, LEN(@sql)-11);

INSERT #d EXEC sp_executesql @sql;

SELECT 
    db+'.'+sch+'.'+obj, 
    ' (' + type_desc + ') references => ',
    COALESCE(ref_db, db)+'.'+ref_sch+'.'+ref_obj
    FROM #d;
GO

DROP TABLE #d;
GO

Sample output:

[db1].[dbo].[foo]  (SQL_STORED_PROCEDURE) references =>   [db2].[dbo].[bar]
[db1].[dbo].[xyz]  (SQL_STORED_PROCEDURE) references =>   [db1].[dbo].[table_xyz]


This should help you get started

create table ##tbData (
DatabaseName Varchar(64),
objectName varchar(128),
ObjectKind varchar(128)
)
go

EXEC sp_Msforeachdb "use [?];
       insert ##tbData select db_name(),so.name,so.xtype from sysobjects so"

select * from ##tbdata

Essentially, build a table and the SQL statement you want to use, then use the undocumented sp_MSforEachdb to load the table from every database


You could look at something like sp_MSForeachdb and call the above query each of those databases.

0

精彩评论

暂无评论...
验证码 换一张
取 消