2011-09-01 108 views
4

我有一个包含多个数据库和客户端应用程序的系统。所有数据库都在一个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 

感谢。

回答

7
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; 

装载表一表的SQL语句编辑

以上将找到每个数据库中的所有引用,但不会找到交叉数据库e参考。它把一个小游戏,并且输出不正是你想要的,但我认为这使得它更不言自明:

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] 
+0

谢谢Aeron。这就是我想要的。 –

+0

但是,如果在另一个数据库的对象中遇到表名Database_name.schema_name.object_name,那么脚本似乎不起作用。 –

+0

@Igor请参阅跨数据库方法的更新答案。 –

0

你可以看看类似sp_MSForeachdb的东西,并调用上述查询每个数据库。

+0

我会写我自己的sp_MSforeachdb之前我会使用微软的内置版本。有关更多详细信息,请参阅我对@ Sparky的答案的评论。 –

+0

虽然我从未真正使用它,但我只是在懒惰的回答下运行,但我并未意识到超出无证/支持范围的行李。 – billinkc

2

这应该可以帮助您从本质上开始

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 

,打造您要使用,然后使用无证sp_MSforEachdb从每个数据库

+1

无法认可sp_MSforeachdb。不仅因为它没有得到支持或记录,而且因为我看到了第一手案件,它破坏了。有关更多详细信息,请参阅http://www.mssqltips.com/tip.asp?tip=2201(另外,为什么是##全局临时表?) –

+0

我选择了一个全局临时表以确保它可以安全地由存储过程。您可以在sp_MSforEachDB调用中使用完全限定的表名执行相同的操作 – Sparky

+0

如果您插入#t exec,普通的#temp表格将正常工作... ## global确保两个人无法运行此代码同时。 –

相关问题