2010-05-07 14 views

回答

0

好吧,我建了一个存储过程要做到这一点,不是很优雅,但希望别人会发现它有用:

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 
相关问题