Найти таблицы, от которых зависит конкретная таблица в SQL Server - PullRequest
1 голос
/ 02 июля 2011

Есть ли способ получить все таблицы, от которых зависит таблица?Должно быть, так как SQL Server Management Studio позволяет вам сделать это, выбрав Найти зависимости, а затем опцию «Объект, от которого [имя таблицы] зависит»

Я знаю о sp_depends, но это возвращает мне объект, которыйзависит от стола, а не от того, от чего зависит стол.

Заранее спасибо,

Джон

Ответы [ 3 ]

2 голосов
/ 02 июля 2011

Основываясь на обсуждении с 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 предполагается, что у вас нет констант, которые удивительно похожи на имена объектов (в частности, я разбираю для]. [Чтобы показать имя функции, так как вы можете ' t оставить схему вне и добавить квадратные скобки), имена функций, которые не содержат специальных символов, таких как «[», «.» или «]», или аргументы, переданные в UDF, содержащие «[» или ']' потому что я использую их, чтобы определить, что это на самом деле функция (и я также предполагаю, что нет вложенных функций). Предполагается также, что все ссылки содержатся в одной базе данных. Еще одно - я углубляюсь на один уровень - если у вас есть триггер на dbo.foo, который вызывает функцию, которая в свою очередь ссылается на другую таблицу, она не будет включена. Бесплатная помощь будет только желающим пройти так далеко вниз по кроличьей норе. : -)

Я до сих пор не доверяю ни одному из представлений зависимостей на 100%, поэтому, если ваша система нестабильна, я бы сказал, что вам лучше всего следовать советам gbn и проводить анализ методом перебора, используя sys.sql_modules.definition для частей этого которые склонны к аннулированию из-за изменений схемы. Есть очень много способов, которыми автоматизация этих вещей может пойти не так, я не знаю, будет ли у вас когда-нибудь 100% пуленепробиваемое решение - хотя с МНОГО работы вы можете быть довольно близко.

Но вернемся к первоначальному вопросу - возможно, вы могли бы точно определить, какие именно типы зависимостей вы ищете.

2 голосов
/ 02 июля 2011

Таблицы обычно не зависят от таблиц, кроме

  • внешние ключи. Используйте sys.foreign_key , object_id и referenced_object_id
  • триггера. Используйте sys.sql_modules и sys.objects.
  • ПРОВЕРЬТЕ ограничения, имеющие UDF. Это сложно, используйте sys.sql_modules и sys.objects снова

Косвенные зависимости, например, то, как выглядят таблицы JOINs 2, будут из некоторых умных запросов в sys.sql_modules

0 голосов
/ 03 августа 2011

Вы пробовали sp_MSdependencies?Он недокументирован, поэтому на него нельзя полностью положиться, но он выглядит достаточно гибким и прекрасно выполняет свою работу ...

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