Найти имя таблицы во всех объектах всех баз данных - PullRequest
4 голосов
/ 01 сентября 2011

У меня есть система с несколькими базами данных и клиентскими приложениями. Все базы данных находятся в одном экземпляре SQL Server. Они были разработаны разными людьми в разное время. Поэтому, если возникает какая-либо ошибка, довольно сложно найти, в какой процедуре или триггере были изменены данные.

Теперь я использую этот скрипт, который нашел на этом сайте:

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.referencing_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

Но этот скрипт, похоже, работает только для базы данных, к которой принадлежит таблица.

Я хочу получить для указанного имени таблицы (или даже лучше для объекта) список всех объектов всех баз данных, в которых встречалось указанное имя таблицы:

Database_Name  SchemaName  ObjectName  ObjectKind  

Спасибо.

Ответы [ 3 ]

7 голосов
/ 01 сентября 2011
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;

РЕДАКТИРОВАТЬ

Выше будут найдены все ссылки в каждой базе данных, но не найдены ссылки между базами данных.Потребовалось немного поиграть, и вывод не совсем то, что вы хотели, но я думаю, что это делает его более понятным:

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

Пример вывода:

[db1].[dbo].[foo]  (SQL_STORED_PROCEDURE) references =>   [db2].[dbo].[bar]
[db1].[dbo].[xyz]  (SQL_STORED_PROCEDURE) references =>   [db1].[dbo].[table_xyz]
2 голосов
/ 01 сентября 2011

Это должно помочь вам начать

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

По сути, создайте таблицу и оператор SQL, который вы хотите использовать, а затем используйте недокументированный sp_MSforEachdb для загрузки таблицы из каждой базы данных

0 голосов
/ 01 сентября 2011

Вы можете посмотреть что-то вроде sp_MSForeachdb и вызвать вышеуказанный запрос к каждой из этих баз данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...