是否可以对我的所有数据库对象运行更改来测试它们

发布于 2024-08-31 19:19:18 字数 83 浏览 5 评论 0原文

我正在进行一些架构迁移,并且想知道是否可以或建议将数据库中的每个存储过程、视图和函数作为alter语句运行以“编译”它们,以确保没有什么是完全的破碎的。

I'm in the course of doing some schema migrations, and would like to know if it's possible or advisable to run every stored procedure, view and function in my database as an alter statement to "compile" them all to make sure nothing is completely broken.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绿萝 2024-09-07 19:19:18

好吧,我构建了一个存储过程来执行此操作,不是很优雅,但希望其他人会发现它有用:

CREATE PROCEDURE [dbo].[UTIL_RunAlterOnAll]
    @debugMessages BIT = 0
AS
BEGIN
    BEGIN TRAN
        SET NOCOUNT ON

        DECLARE @allAlterTexts TABLE (name VARCHAR(256), alterText NVARCHAR(MAX), id INT, type CHAR(2))

        DECLARE @rowsInError TABLE (errorMessage NVARCHAR(2048), errorNumber INT, name VARCHAR(256), alterText NVARCHAR(MAX), id INT, type CHAR(2))

        ;WITH Texts AS
        (
            SELECT o.name, o.type, sm.definition AS text, o.id
            FROM sysobjects AS o
            INNER JOIN sys.sql_modules AS sm
            ON sm.object_id = o.id
            WHERE o.type IN ('P', 'V', 'FN')
        )
        INSERT INTO @allAlterTexts (name, alterText, id, type)
        SELECT name, alterStatement, id, type
        FROM
        (
            SELECT name, REPLACE(text, 'CREATE PROCEDURE', 'ALTER PROCEDURE') AS alterStatement, id, type
            FROM Texts AS procs
            WHERE procs.type = 'P'
            UNION ALL
            SELECT name, REPLACE(text, 'CREATE VIEW', 'ALTER VIEW') AS alterStatement, id, type
            FROM Texts AS procs
            WHERE procs.type = 'V'
            UNION ALL
            SELECT name, REPLACE(text, 'CREATE FUNCTION', 'ALTER FUNCTION') AS alterStatement, id, type
            FROM Texts AS procs
            WHERE procs.type = 'FN'
        ) AS allAlters

        DECLARE curs CURSOR FORWARD_ONLY
        FOR
            SELECT *
            FROM @allAlterTexts

        DECLARE @name VARCHAR(MAX)
            , @alterText VARCHAR(MAX)
            , @id INT
            , @type VARCHAR(2)

        OPEN curs
            FETCH NEXT FROM curs
            INTO @name, @alterText, @id, @type

            WHILE @@FETCH_STATUS = 0
            BEGIN
                IF @debugMessages = 1
                BEGIN
                    PRINT 'Alter text for @name'
                    PRINT '-----'
                    PRINT @alterText
                    PRINT '-----'
                END

                BEGIN TRY
                    IF @debugMessages = 1
                    BEGIN
                        PRINT 'Running ' + @name
                    END
                        EXEC(@alterText)
                    IF @debugMessages = 1
                    BEGIN
                        PRINT 'Success'
                    END
                END TRY
                BEGIN CATCH
                    IF @debugMessages = 1
                    BEGIN
                        PRINT 'ERROR!'
                        PRINT ERROR_MESSAGE()
                        PRINT '----'
                        PRINT 'Text:'
                        PRINT @alterText
                    END

                    INSERT INTO @rowsInError (errorMessage, errorNumber, name, alterText, id, type)
                    VALUES(LTRIM(RTRIM(ERROR_MESSAGE())), ERROR_NUMBER(), @name, @alterText, @id, @type)
                END CATCH


                IF @debugMessages = 1
                BEGIN
                    PRINT '-----'
                END

                FETCH NEXT FROM curs
                INTO @name, @alterText, @id, @type
            END
        CLOSE curs

        DEALLOCATE curs
        SET NOCOUNT OFF

        -- WTF? 3930 means transaction error, these get raised whenever another error is raised, 
        -- as the transaction is set to invalid
        SELECT *
        FROM @rowsInError
        WHERE errorNumber != 3930
        ORDER BY name

    ROLLBACK TRAN
END
GO

Well, I built a sproc to do this, not very elegant, but hopefully someone else will find it useful:

CREATE PROCEDURE [dbo].[UTIL_RunAlterOnAll]
    @debugMessages BIT = 0
AS
BEGIN
    BEGIN TRAN
        SET NOCOUNT ON

        DECLARE @allAlterTexts TABLE (name VARCHAR(256), alterText NVARCHAR(MAX), id INT, type CHAR(2))

        DECLARE @rowsInError TABLE (errorMessage NVARCHAR(2048), errorNumber INT, name VARCHAR(256), alterText NVARCHAR(MAX), id INT, type CHAR(2))

        ;WITH Texts AS
        (
            SELECT o.name, o.type, sm.definition AS text, o.id
            FROM sysobjects AS o
            INNER JOIN sys.sql_modules AS sm
            ON sm.object_id = o.id
            WHERE o.type IN ('P', 'V', 'FN')
        )
        INSERT INTO @allAlterTexts (name, alterText, id, type)
        SELECT name, alterStatement, id, type
        FROM
        (
            SELECT name, REPLACE(text, 'CREATE PROCEDURE', 'ALTER PROCEDURE') AS alterStatement, id, type
            FROM Texts AS procs
            WHERE procs.type = 'P'
            UNION ALL
            SELECT name, REPLACE(text, 'CREATE VIEW', 'ALTER VIEW') AS alterStatement, id, type
            FROM Texts AS procs
            WHERE procs.type = 'V'
            UNION ALL
            SELECT name, REPLACE(text, 'CREATE FUNCTION', 'ALTER FUNCTION') AS alterStatement, id, type
            FROM Texts AS procs
            WHERE procs.type = 'FN'
        ) AS allAlters

        DECLARE curs CURSOR FORWARD_ONLY
        FOR
            SELECT *
            FROM @allAlterTexts

        DECLARE @name VARCHAR(MAX)
            , @alterText VARCHAR(MAX)
            , @id INT
            , @type VARCHAR(2)

        OPEN curs
            FETCH NEXT FROM curs
            INTO @name, @alterText, @id, @type

            WHILE @@FETCH_STATUS = 0
            BEGIN
                IF @debugMessages = 1
                BEGIN
                    PRINT 'Alter text for @name'
                    PRINT '-----'
                    PRINT @alterText
                    PRINT '-----'
                END

                BEGIN TRY
                    IF @debugMessages = 1
                    BEGIN
                        PRINT 'Running ' + @name
                    END
                        EXEC(@alterText)
                    IF @debugMessages = 1
                    BEGIN
                        PRINT 'Success'
                    END
                END TRY
                BEGIN CATCH
                    IF @debugMessages = 1
                    BEGIN
                        PRINT 'ERROR!'
                        PRINT ERROR_MESSAGE()
                        PRINT '----'
                        PRINT 'Text:'
                        PRINT @alterText
                    END

                    INSERT INTO @rowsInError (errorMessage, errorNumber, name, alterText, id, type)
                    VALUES(LTRIM(RTRIM(ERROR_MESSAGE())), ERROR_NUMBER(), @name, @alterText, @id, @type)
                END CATCH


                IF @debugMessages = 1
                BEGIN
                    PRINT '-----'
                END

                FETCH NEXT FROM curs
                INTO @name, @alterText, @id, @type
            END
        CLOSE curs

        DEALLOCATE curs
        SET NOCOUNT OFF

        -- WTF? 3930 means transaction error, these get raised whenever another error is raised, 
        -- as the transaction is set to invalid
        SELECT *
        FROM @rowsInError
        WHERE errorNumber != 3930
        ORDER BY name

    ROLLBACK TRAN
END
GO
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文