Как получить правильный порядок для создания хранимой процедуры, пользовательских функций и триггеров - PullRequest
1 голос
/ 21 декабря 2010

Я прочитал, что объектные зависимости были улучшены в SQL Server 2008.

У меня довольно сложная схема базы данных, содержащая хранимые процедуры, пользовательские функции, триггеры.

Может кто-нибудь дать мнезапрос, который вернул бы правильный порядок создания этих элементов на основе их зависимостей?

Я прочитал здесь , что существуют инструменты, которые могут выполнить эту работу, но я ищу что-то, что можно написать,Кроме того, они часто дают зависимости одного объекта, и я хотел бы решения для всей базы данных.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 21 декабря 2010

Redgate sql Compare Pro может быть выполнен через командную строку. У меня есть версия с графическим интерфейсом, и она всегда исправляет ситуацию. Я даже узнал несколько вещей, посмотрев на результат этого инструмента!

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

0 голосов
/ 22 декабря 2010

Ну, я сделал что-то на основе этой статьи

Я изменил sp_FindDependencies, чтобы включить уровень в дерево зависимостей:

 CREATE PROCEDURE sp_FindDependencies
 (
         @ObjectName SYSNAME,
         @ObjectType VARCHAR(5) = NULL
 )
 AS
 BEGIN
     DECLARE @ObjectID AS BIGINT    

         SELECT TOP(1) @ObjectID = object_id
         FROM sys.objects
         WHERE name = @ObjectName
         AND type = ISNULL(@ObjectType, type)    

     SET NOCOUNT ON ;    

       WITH DependentObjectCTE (DependentObjectID, DependentObjectName, ReferencedObjectName, ReferencedObjectID, Level)
         AS
         (
         SELECT DISTINCT
                sd.object_id,
                OBJECT_NAME(sd.object_id),
                ReferencedObject = OBJECT_NAME(sd.referenced_major_id),
                ReferencedObjectID = sd.referenced_major_id,
                1 AS Level
         FROM    
                sys.sql_dependencies sd
                JOIN sys.objects so ON sd.referenced_major_id = so.object_id
         WHERE   
                sd.referenced_major_id = @ObjectID
         UNION ALL
         SELECT
                sd.object_id,
                OBJECT_NAME(sd.object_id),
                OBJECT_NAME(referenced_major_id),
                object_id,
                Level + 1
         FROM    
                sys.sql_dependencies sd
             JOIN DependentObjectCTE do ON sd.referenced_major_id = do.DependentObjectID       
         WHERE
                sd.referenced_major_id <> sd.object_id     
         )
         SELECT DISTINCT
                DependentObjectName, Level
         FROM   
                DependentObjectCTE c
 END
GO

Затем я прошёлвсе объекты, которые я хочу отследить.В моей системе я поддерживаю версию этих объектов в таблице SpVersion.

DECLARE @err int;
DECLARE @level int;
DECLARE @name varchar(50);
DECLARE @name2 varchar(50);

DECLARE cur CURSOR LOCAL FAST_FORWARD FOR 
SELECT SP.name AS obj_name
FROM sys.procedures SP, SpVersion SPV WHERE
SP.name = SPV.SpName
UNION
SELECT SO.name AS obj_name
FROM sys.objects SO, SpVersion SPV 
WHERE type_desc LIKE '%FUNCTION%' AND SO.name=SPV.SpName
UNION
SELECT ST.name AS obj_name
FROM sys.triggers ST, SpVersion SPV 
WHERE ST.name=SPV.SpName;

CREATE TABLE #T1 (procname varchar(50) COLLATE DATABASE_DEFAULT, Level int);
CREATE TABLE #T2 (procname varchar(50) COLLATE DATABASE_DEFAULT, Level int);

OPEN cur
SELECT @err = @@error IF @err <> 0 RETURN  

WHILE 1=1 BEGIN
    FETCH NEXT FROM cur INTO @name
    SELECT @err = @@error IF @err <> 0 RETURN 
    IF @@FETCH_STATUS <> 0 BREAK

    DELETE #T1;
    INSERT #T1 (procname, level) VALUES (@name, 0);
    INSERT #T1 (procname, level) EXEC sp_FindDependencies @name;

    DECLARE cur2 CURSOR LOCAL FAST_FORWARD FOR 
    SELECT procname, level FROM #T1;

    OPEN cur2
    SELECT @err = @@error IF @err <> 0 RETURN  

    WHILE 1=1 BEGIN
        FETCH NEXT FROM cur2 INTO @name2, @level
        SELECT @err = @@error IF @err <> 0 RETURN 
        IF @@FETCH_STATUS <> 0 BREAK

        PRINT @name;
        PRINT CONVERT(nvarchar, @level)

        IF NOT EXISTS(SELECT 1 FROM #T2 WHERE procname = @name) BEGIN
            INSERT INTO #T2 (procname, level) VALUES (@name, @level);
        END ELSE BEGIN
            UPDATE #T2 SET level=@level WHERE procname=@name;
        END
    END

    CLOSE cur2;
    DEALLOCATE cur2;
END

CLOSE cur;
DEALLOCATE cur;

SELECT * FROM #T2 ORDER BY Level DESC;

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