查找特定表在SQL Server中依赖的表

时间:2011-07-02 12:40:55

标签: sql sql-server sql-server-2008

有没有办法获得表所依赖的所有表?必须有SQL Server Management Studio允许您通过选择查找依赖项,然后选择'对象[tablename]依赖于'

来执行此操作

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

提前致谢,

乔恩

3 个答案:

答案 0 :(得分:2)

表通常不依赖于

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

间接依赖关系,比如查看JOINs 2表将来自sys.sql_modules上的一些聪明的查询

答案 1 :(得分: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

好的,既然数据库充满了要查找的东西,下面的脚本将识别上面的所有对象引用:

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中的定义解析假定你没有看起来非常像对象名称的常量(特别是我解析)。[显示一个函数名,因为你可以'退出架构并为您添加方括号),不包含特殊字符的函数名称,如“[”,“。”或“]”,或者将参数传递给包含'['或']'因为我使用它们来确定它实际上是一个函数(我还假设没有嵌套函数)。它还假定所有引用都包含在同一数据库中。还有一个是我只深入一层 - 如果你在dbo.foo上有一个触发器,它调用一个函数来反过来引用另一个表,那么它将不被包括在内。免费帮助只能在兔子洞里走得那么远。 : - )

我仍然不相信任何依赖关系视图100%,所以如果你的系统是不稳定的,我会说你最安全的选择是遵循gbn的建议并使用sys.sql_modules.definition进行暴力解析。由于架构更改而容易失效的情况。有很多方法可以自动化这些东西可能会出错,我不知道你是否会有100%的防弹解决方案 - 尽管有很多工作可以让你非常接近。

但回到最初的问题 - 也许你可以明确地定义你正在寻找的依赖类型。

答案 2 :(得分:0)

您是否尝试过sp_MSdependencies?它没有文档,所以你不能完全依赖它, 但它看起来非常灵活,能很好地完成它的工作......