2011-07-02 37 views
1

有没有办法获取表格所依赖的所有表格?必须有SQL Server Management Studio允许你通过选择Find Dependencies然后选择'Objectname'[tablename]依赖于'在SQL Server中查找特定表所依赖的表格

我知道sp_depends,但是这会让我回到依赖于表的对象而不是桌子依赖于什么。

由于提前,

乔恩

+1

通过打开SQL事件探查器并捕获Management Studio运行的查询,您可能确实很狡猾 - 在Profiler中,一定要禁用删除Management Studio查询的列过滤器。 –

回答

2

根据与GBN和讨论你只关心表取决于(而不是任何取决于表)中的对象的假设,我想出了这个人为的例子:

USE [master]; 
GO 

IF DB_ID('foo') IS NOT NULL 
    DROP DATABASE foo; 
GO 

CREATE DATABASE foo; 
GO 

USE foo; 
GO 

CREATE TYPE dbo.Email FROM VARCHAR(320) NOT NULL; 
GO 

CREATE SCHEMA foo AUTHORIZATION dbo; 
GO 

CREATE TYPE foo.Email FROM VARCHAR(320) NULL; 
GO 

CREATE FUNCTION dbo.IsGreaterThanZero1(@i INT) 
RETURNS BIT 
AS 
BEGIN 
    RETURN (SELECT CASE WHEN @i>0 THEN 1 ELSE 0 END); 
END 
GO 

CREATE FUNCTION dbo.IsGreaterThanZero2(@i INT) 
RETURNS BIT 
AS 
BEGIN 
    RETURN (SELECT CASE WHEN @i>0 THEN 1 ELSE 0 END); 
END 
GO 

CREATE TABLE dbo.bar 
(
    id INT PRIMARY KEY 
); 
GO 

CREATE FUNCTION dbo.maxbar() 
RETURNS INT 
AS 
BEGIN 
    RETURN (SELECT MAX(id) FROM dbo.bar); 
END 
GO 

CREATE TABLE dbo.foo 
(
    id INT FOREIGN KEY REFERENCES dbo.bar(id), 
     -- dependency on foreign key to another table 
    Email1 dbo.Email, 
     -- dependency on alias type 
    Email2 foo.Email, 
     -- dependency on alias type in different schema 
    IsMoreThanZero1 AS CONVERT(BIT, dbo.IsGreaterThanZero1(id)), 
     -- computed column dependency 
    IsMoreThanZero1A AS dbo.IsGreaterThanZero1(id), 
     -- computed column dependency 
    IsMoreThanZero2 BIT CHECK (dbo.IsGreaterThanZero2(IsMoreThanZero2)=1), 
     -- check constraint dependency 
    IsMoreThanZero2A BIT CHECK (CONVERT(BIT,  
      dbo.IsGreaterThanZero2(IsMoreThanZero2A))=1), 
     CHECK(IsMoreThanZero2A LIKE '[,%]'), 
     -- check constraint dependency 
    maxbar INT NOT NULL DEFAULT (dbo.maxbar()) 
     -- default constraint dependency 
); 
GO 

CREATE TRIGGER dbo.after_insert_foo ON dbo.foo 
FOR INSERT 
AS 
BEGIN 
    SET NOCOUNT ON; 
    DECLARE @x INT; 
    SELECT TOP (1) @x = id FROM dbo.bar; 
END 
GO 

好了,现在该数据库是座充满的东西要找到,以下脚本将标识所有对象引用ces以上:

DECLARE @tablename SYSNAME = N'dbo.foo'; 

DECLARE @object_id INT = OBJECT_ID(@tablename); 

-- functions mentioned in check/default constraints 
-- and computed columns in @tablename 

WITH x AS 
(
    SELECT [type], [obj], [count] = COUNT(*) 
    FROM 
    (
     SELECT [type], obj = OBJECT_ID( 
      SUBSTRING(d, CHARINDEX('],', d) + 2, 
       CHARINDEX('(', SUBSTRING(d, 
       CHARINDEX('],', d) + 2, LEN(d)))-1)) 
     FROM 
     (
      SELECT [type] = 'default', [object_id], d = [definition] 
      FROM sys.default_constraints 
      WHERE parent_object_id = @object_id 
      AND CHARINDEX('].[', [definition]) > 0 
      UNION 
      SELECT 'check', [object_id], [definition] 
      FROM sys.check_constraints 
      WHERE parent_object_id = @object_id 
      AND CHARINDEX('].[', [definition]) > 0 
      UNION 
      SELECT 'computed', NULL, [definition] 
      FROM sys.computed_columns 
      WHERE [object_id] = @object_id 
      AND CHARINDEX('].[', [definition]) > 0 
     ) AS x 
    ) AS y GROUP BY [type], [obj] 

    UNION ALL 

    -- triggers defined on @tablename 
    SELECT 'trigger', obj = [object_id], 1 
     FROM sys.triggers 
     WHERE parent_id = @object_id 

    UNION ALL 

    -- objects referenced by triggers on @tablename 
    SELECT 'trigger references', [obj] = d.[referenced_major_id], COUNT(*) 
     FROM sys.sql_dependencies AS d 
     INNER JOIN sys.triggers AS tr 
     ON d.[object_id] = tr.[object_id] 
     AND tr.parent_id = @object_id 
     GROUP BY d.referenced_major_id 

    UNION ALL 

    -- foreign keys referenced by @tablename 
    SELECT 'foreign key', [obj] = referenced_object_id, COUNT(*) 
     FROM sys.foreign_keys 
     WHERE parent_object_id = @object_id 
     GROUP BY referenced_object_id 
) 
SELECT 
    [obj] = QUOTENAME(OBJECT_SCHEMA_NAME(obj)) + '.' 
      + QUOTENAME(OBJECT_NAME(obj)), 
    [type], 
    [count] 
FROM x 
UNION ALL 
SELECT 
    [obj], 
    [type], 
    [count] = COUNT(*) 
FROM 
(
    SELECT 
     [obj] = QUOTENAME(SCHEMA_NAME(t.[schema_id])) 
      + '.' + QUOTENAME(t.name), 
     [type] = 'alias type' 
    FROM 
     sys.types AS t 
     INNER JOIN sys.columns AS c 
     ON t.user_type_id = c.user_type_id 
     WHERE t.is_user_defined = 1 
     AND c.[object_id] = @object_id 
) AS x GROUP BY [obj], [type]; 

这里有更多的注意事项比我不在乎。一个是,在sys.default_constraints,sys.check_constraints和sys.computed_columns中的定义分析假定你没有看起来像对象名称(特别是我解析为)的常量[显示函数名称,因为你可以' t将模式和方括号添加为您),不包含特殊字符(如“[”,“。”或“]”)的函数名称,或者传递给包含'['的UDF或']',因为我使用这些来确定它实际上是一个函数(并且我还假定没有嵌套函数)。它还假定所有的引用都包含在同一个数据库中。还有一点是我只深入一层 - 如果你在dbo.foo上有一个触发器,它会调用一个函数,该函数又引用另一个表,而这个表不会被包含在内。免费的帮助只会愿意走到兔子洞的尽头。 :-)

我仍然不信任任何依赖性视图100%,所以如果你的系统是不稳定的,我会说你最安全的赌注是遵循gbn的建议,并使用sys.sql_modules.definition来追求暴力破解由于模式更改,这部分容易失效。只有很多方法可以使这些东西自动化出错,我不知道你是否会有100%的防弹解决方案 - 尽管有很多工作可以让你变得非常接近。

但回到原来的问题 - 也许你可以明确定义你正在寻找哪些类型的依赖关系。

2

表通常不依赖于表除了

  • 外键。使用sys.foreign_key,object_id和referenced_object_id列
  • 触发器。使用sys.sql_modules和sys.objects。
  • 检查具有UDF的约束。棘手的这一点,再次使用sys.sql_modules和sys.objects中

间接依赖,像什么看法JOIN的2桌都将是从一些聪明的查询上sys.sql_modules

+0

即使是最后一个,视图依赖于表格,而不是相反。也有可能属于该要求的别名类型。 –

+0

@Aaron Bertrand:是的,但如果OP意味着“相关”而不是“依赖”,那么它仍然是sys.sql_modules上的一个聪明的查询。无论如何这都是一个混乱的要求。 – gbn

+0

查看 - >表关系实际上应该很简单(sys.sql_dependencies)。 –

0

您是否尝试过sp_MSdependencies?这是无证的,所以你不能完全依靠它,但它似乎很灵活,很好地完成它的工作......

相关问题