2012-12-07 42 views
8

SQL Server版本 - 2008 R2获取SQL Server跨数据库依赖关系

我正在评估DMS解决方案,目标是接管维护。原始解决方案有一个中央数据库,其中包含与制造商有关的数据。它还为每个经销商提供一个数据库,这意味着存在大量的跨数据库依赖关系。

的问题:

  • 没有DB文档
  • 没有代码注释
  • 大量堆
  • 没有标准的对象命名约定
  • 的DB中央有460+表和存储过程900+ ,除了其他 对象
  • 每个经销商DB有370+表和2350+ SProcs,另外n至其他 对象

作为第一步,我建议的DB,为此,关键是要理解对象依赖性,包括跨数据库依赖关系的完整的清理。我尝试过使用Red Gate的解决方案,但输出方式太庞大。我所需要的是数据库中没有任何依赖关系的对象列表 - 它们既不依赖于其他对象,也不依赖于依赖它们的任何对象。

这里是我用来获取相关性列表的脚本:

SELECT 
DB_NAME() referencing_database_name, 
OBJECT_NAME (referencing_id) referencing_entity_name, 
ISNULL(referenced_schema_name,'dbo') referenced_schema_name, 
referenced_entity_name, 
ao.type_desc referenced_entity_type, 
ISNULL(referenced_database_name,DB_NAME()) referenced_database_name 
FROM sys.sql_expression_dependencies sed 
JOIN sys.all_objects ao 
ON sed.referenced_entity_name = ao.name 

我将创建一个表 - 依赖 - 到了我会被插入这个结果从每个DB设置。作为下一步,我还将创建另一个表 - AllObjects - 它将包含数据库中所有对象的列表。这里是脚本来做到这一点:

SELECT 
DB_NAME() DBName, 
name, 
type_desc 
FROM sys.all_objects 
WHERE type_desc IN 
(
'VIEW', 
'SQL_TABLE_VALUED_FUNCTION', 
'SQL_STORED_PROCEDURE', 
'SQL_INLINE_TABLE_VALUED_FUNCTION', 
'USER_TABLE', 
'SQL_SCALAR_FUNCTION' 
) 

现在,从该表中,没有出现在依赖关系表中的列referenced_entity_name应该给我找的对象列表名称的列表。

SELECT 
AO.DBName, 
AO.name, 
AO.type_desc 
FROM AllObjects AO 
LEFT OUTER JOIN Dependencies D ON 
D.referenced_database_name = AO.DBName AND 
D.referenced_entity_name = AO.name AND 
D.referenced_entity_type = AO.type_desc 
WHERE 
D.referenced_database_name IS NULL AND 
D.referenced_entity_name IS NULL AND 
D.referenced_entity_type IS NULL 

现在的问题:

  1. 一些对象依赖似乎在输出中丢失。我缺少什么 ?
  2. 我如何验证我的发现是正确的?
  3. 我的意思是有不同的方式来做到这一点,所以我可以比较 结果和双重检查?

由于提前,

拉吉

+0

你也关心SYSTEM对象吗? –

+0

但是type ='U'只会给用户表,对不对?我还需要考虑其他用户创建的对象。 – Raj

+0

对不起,“and is_ms_shipped = 0”可能更适合第二个查询。这应该排除系统特定的对象。 –

回答

3

哦,MS在检测与sys.sql_expression_dependencies跨数据库的依赖关系取得了不错的努力,但我已经看到了以前错过的东西。在你的情况下,我会找到一个缺失依赖的例子,并开始回溯:你是否从查询中删除了它的一些方法?如果是这样,请修复您的查询。 sys.sql_expression_dependencies是否忽略了某个类的依赖关系?在什么条件下?是动态SQL的责任?等等

您还应该为sys.sql_modules中的每个对象运行​​,然后重新运行您的代码。它强制SQL Server刷新依赖关系信息(尽其所能)。

现在,为验证,设置跟踪并监听事件114“审计模式对象访问事件”,以及存储过程和/或RPC调用的启动和完成事件。包括列DatabaseName,ParentName,ObjectName,ServerName,SPIDRequestID(对于MARS启用的连接)。也许也有其他人。 “审计模式对象访问事件”在访问对象时发生,因此在此跟踪运行时应用该应用程序,然后使用SPID + RequestId整理数据,并使用sys.sql_expression_dependencies将其与结果进行比较。如果跟踪数据中没有任何内容出现在您的依赖关系数据中,那么您错过了某些内容。

7

您可以将结果与以下脚本找到的结果进行比较。 这里是完整的article

CREATE PROCEDURE [dbo].[get_crossdatabase_dependencies] AS 

SET NOCOUNT ON; 

CREATE TABLE #databases(
    database_id int, 
    database_name sysname 
); 

INSERT INTO #databases(database_id, database_name) 
SELECT database_id, [name] 
FROM sys.databases 
WHERE 1 = 1 
    AND [state] <> 6 /* ignore offline DBs */ 
    AND database_id > 4; /* ignore system DBs */ 

DECLARE 
    @database_id int, 
    @database_name sysname, 
    @sql varchar(max); 

CREATE TABLE #dependencies(
    referencing_database varchar(max), 
    referencing_schema varchar(max), 
    referencing_object_name varchar(max), 
    referenced_server varchar(max), 
    referenced_database varchar(max), 
    referenced_schema varchar(max), 
    referenced_object_name varchar(max) 
); 

WHILE (SELECT COUNT(*) FROM #databases) > 0 BEGIN 
    SELECT TOP 1 @database_id = database_id, 
       @database_name = database_name 
    FROM #databases; 

    SET @sql = 'INSERT INTO #dependencies select 
     DB_NAME(' + convert(varchar,@database_id) + '), 
     OBJECT_SCHEMA_NAME(referencing_id,' 
      + convert(varchar,@database_id) +'), 
     OBJECT_NAME(referencing_id,' + convert(varchar,@database_id) + '), 
     referenced_server_name, 
     ISNULL(referenced_database_name, db_name(' 
      + convert(varchar,@database_id) + ')), 
     referenced_schema_name, 
     referenced_entity_name 
    FROM ' + quotename(@database_name) + '.sys.sql_expression_dependencies'; 

    EXEC(@sql); 

    DELETE FROM #databases WHERE database_id = @database_id; 
END; 

SET NOCOUNT OFF; 

SELECT * FROM #dependencies; 
+1

请注意,如果数据库处于脱机状态,它仍会尝试访问,因此会出错 –

+0

好点,我只是在WHERE过滤器中添加一行以忽略脱机数据库^ _ ^ – Oreo