web-dev-qa-db-fra.com

Comment générer des scripts pour tous les déclencheurs d'une base de données à l'aide de Microsoft SQL Server Management Studio

J'aimerais générer un script SQL contenant le code SQL afin de créer tous les déclencheurs existant dans notre base de données. Les déclencheurs ont été ajoutés directement via le volet de requête SSMS. Il n’existe actuellement aucune source autre que le déclencheur de la base de données elle-même. 

J'ai déjà essayé la méthode qui consiste à cliquer avec le bouton droit de la souris sur la base de données, à sélectionner Tasks->Generate Scripts et à utiliser l'option "Script pour la base de données complète et tous les objets". Bien que cela crée un script SQL pour les tables et les contraintes, il ne génère pas de code SQL pour les déclencheurs. 

Je comprends également que je peux cliquer avec le bouton droit de la souris sur chaque déclencheur de la base de données et sélectionner l’option Générer un script SQL, mais 46 tables sont actuellement en cours d’audit (pour les opérations d’insertion, de mise à jour et de suppression). 

Générez plutôt manuellement un script de déclencheur d'insertion, de mise à jour et de suppression pour chacune des 46 tables. Existe-t-il un moyen plus simple de procéder? Ou devrais-je commencer à cliquer, copier et coller?

51
Grasshopper

Base de données-> Tâches-> Générer des scripts -> Suivant -> Suivant

Sur Choisissez Options de script UI, sous Tableau/Options d'affichage Titre, définissez Script Triggers sur True .

enter image description here

enter image description here

76
Kapil Khandelwal

Je sais que la réponse a déjà été acceptée, mais je souhaite fournir une autre solution lorsque, pour une raison quelconque, l’assistant SSMS n’est pas en mesure de générer un script pour les déclencheurs (dans mon cas c’était MSSQL2008R2).

Cette solution est basée sur l'idée de dana ci-dessus, mais utilise 'sql_modules' à la place pour fournir le code complet du déclencheur s'il dépasse 4000 caractères (restriction de la colonne 'text' de la vue 'syscomments')

select [definition],'GO' from sys.sql_modules m
inner join sys.objects obj on obj.object_id=m.object_id 
 where obj.type ='TR'

Faites un clic droit sur la grille de résultats puis "Enregistrer les résultats sous ..." enregistre dans le fichier avec le formatage conservé

45
Igor

Que dis-tu de ça?

select text from syscomments where text like '%CREATE TRIGGER%'

EDIT- par le commentaire de jj ci-dessous, syscomments est obsolète et sera supprimé à l'avenir. Veuillez utiliser les solutions basées sur un assistant ou sur un script répertoriées ci-dessus pour aller de l'avant :)

5
dana

Pour scripter tous les déclencheurs, vous pouvez définir la procédure stockée:

SET ANSI_NULLS ON; 
GO 
SET QUOTED_IDENTIFIER ON; 
GO 
-- Procedure:
--   [dbo].[SYS_ScriptAllTriggers]
--
-- Parameter: 
--   @ScriptMode bit   
--     possible values:
--     0 - Script ALTER only
--     1 - Script CREATE only
--     2 - Script DROP + CREATE

ALTER PROCEDURE [dbo].[SYS_ScriptAllTriggers]
    @ScriptMode int = 0
AS 
BEGIN

    DECLARE @script TABLE (script varchar(max), id int identity (1,1))

    DECLARE 
        @SQL VARCHAR(8000), 
        @Text            NVARCHAR(4000), 
        @BlankSpaceAdded INT, 
        @BasePos         INT, 
        @CurrentPos      INT, 
        @TextLength      INT, 
        @LineId          INT, 
        @MaxID           INT, 
        @AddOnLen        INT, 
        @LFCR            INT, 
        @DefinedLength   INT, 
        @SyscomText      NVARCHAR(4000), 
        @Line            NVARCHAR(1000), 
        @UserName        SYSNAME, 
        @ObjID           INT, 
        @OldTrigID       INT; 

    SET NOCOUNT ON; 
    SET @DefinedLength = 1000; 
    SET @BlankSpaceAdded = 0; 

    SET @ScriptMode = ISNULL(@ScriptMode, 0);

    -- This Part Validated the Input parameters   
    DECLARE @Triggers TABLE (username SYSNAME NOT NULL, trigname SYSNAME NOT NULL, objid INT NOT NULL); 
    DECLARE @TrigText TABLE (objid INT NOT NULL, lineid INT NOT NULL, linetext NVARCHAR(1000) NULL); 

    INSERT INTO 
        @Triggers (username, trigname, objid) 
    SELECT DISTINCT 
        OBJECT_SCHEMA_NAME(B.id), B.name, B.id
    FROM 
        dbo.sysobjects B, dbo.syscomments C 
    WHERE 
        B.type = 'TR' AND B.id = C.id AND C.encrypted = 0; 

    IF EXISTS(SELECT C.* FROM syscomments C, sysobjects O WHERE O.id = C.id AND O.type = 'TR' AND C.encrypted = 1) 
    BEGIN 

        insert into @script select '/*'; 
        insert into @script select 'The following encrypted triggers were found'; 
        insert into @script select 'The procedure could not write the script for it'; 

        insert into 
            @script 
        SELECT DISTINCT 
            '[' + OBJECT_SCHEMA_NAME(B.id) + '].[' + B.name + ']' --, B.id 
        FROM   
            dbo.sysobjects B, dbo.syscomments C 
        WHERE  
            B.type = 'TR' AND B.id = C.id AND C.encrypted = 1; 

        insert into @script select '*/'; 
    END; 

    DECLARE ms_crs_syscom CURSOR LOCAL forward_only FOR 
    SELECT 
        T.objid, C.text
    FROM   
        @Triggers T, dbo.syscomments C 
    WHERE  
        T.objid = C.id 
    ORDER  BY T.objid, 
        C.colid 
    FOR READ ONLY; 

    SELECT @LFCR = 2; 
    SELECT @LineId = 1; 

    OPEN ms_crs_syscom; 

    SET @OldTrigID = -1; 

    FETCH NEXT FROM ms_crs_syscom INTO @ObjID, @SyscomText; 

    WHILE @@fetch_status = 0 
    BEGIN 

        SELECT @BasePos = 1; 
        SELECT @CurrentPos = 1; 
        SELECT @TextLength = LEN(@SyscomText); 

        IF @ObjID <> @OldTrigID 
        BEGIN 
            SET @LineID = 1; 
            SET @OldTrigID = @ObjID; 
        END; 

        WHILE @CurrentPos != 0 
        BEGIN 
            --Looking for end of line followed by carriage return         
            SELECT @CurrentPos = CHARINDEX(CHAR(13) + CHAR(10), @SyscomText, @BasePos); 

            --If carriage return found         
            IF @CurrentPos != 0 
            BEGIN 

                WHILE ( ISNULL(LEN(@Line), 0) + @BlankSpaceAdded + @CurrentPos - @BasePos + @LFCR ) > @DefinedLength 
                BEGIN 
                    SELECT @AddOnLen = @DefinedLength - (ISNULL(LEN(@Line), 0) + @BlankSpaceAdded ); 

                    INSERT 
                        @TrigText 
                    VALUES 
                        ( @ObjID, @LineId, ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N'')); 

                    SELECT 
                        @Line = NULL, 
                        @LineId = @LineId + 1, 
                        @BasePos = @BasePos + @AddOnLen, 
                        @BlankSpaceAdded = 0; 
                END; 

                SELECT @Line = ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @CurrentPos - @BasePos + @LFCR), N''); 

                SELECT @BasePos = @CurrentPos + 2; 

                INSERT 
                    @TrigText 
                VALUES
                    ( @ObjID, @LineId, @Line ); 

                SELECT @LineId = @LineId + 1; 

                SELECT @Line = NULL; 
            END; 
            ELSE 
            --else carriage return not found         
            BEGIN 
                IF @BasePos <= @TextLength 
                BEGIN 
                    /*If new value for @Lines length will be > then the         
                    **defined length         
                    */ 
                    WHILE ( ISNULL(LEN(@Line), 0) + @BlankSpaceAdded + @TextLength - @BasePos + 1 ) > @DefinedLength 
                    BEGIN 
                        SELECT @AddOnLen = @DefinedLength - ( ISNULL(LEN(@Line), 0 ) + @BlankSpaceAdded ); 

                        INSERT 
                            @TrigText 
                        VALUES 
                            ( @ObjID, @LineId, ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N'')); 

                        SELECT 
                            @Line = NULL, 
                            @LineId = @LineId + 1, 
                            @BasePos = @BasePos + @AddOnLen, 
                            @BlankSpaceAdded = 0; 
                    END; 

                    SELECT @Line = ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @TextLength - @BasePos+1 ), N''); 

                    IF LEN(@Line) < @DefinedLength AND CHARINDEX(' ', @SyscomText, @TextLength + 1) > 0 
                    BEGIN 
                        SELECT 
                            @Line = @Line + ' ', 
                            @BlankSpaceAdded = 1; 
                    END; 
                END; 
            END; 
        END; 

        FETCH NEXT FROM ms_crs_syscom INTO @ObjID, @SyscomText; 
    END; 

    IF @Line IS NOT NULL 
        INSERT 
            @TrigText 
        VALUES
            ( @ObjID, @LineId, @Line ); 

    CLOSE ms_crs_syscom; 

    insert into @script select '-- You should run this result under dbo if your triggers belong to multiple users'; 
    insert into @script select ''; 

    IF @ScriptMode = 2 
    BEGIN 

        insert into @script select '-- Dropping the Triggers'; 
        insert into @script select ''; 

        insert into @script 
        SELECT 
            'IF EXISTS(SELECT * FROM sysobjects WHERE id = OBJECT_ID(''[' + username + '].[' + trigname + ']'')'
            + ' AND ObjectProperty(OBJECT_ID(''[' + username + '].[' + trigname + ']''), ''ISTRIGGER'') = 1)'
            + ' DROP TRIGGER [' + username + '].[' + trigname +']' + CHAR(13) + CHAR(10) 
            + 'GO' + CHAR(13) + CHAR(10)
        FROM   
            @Triggers; 
    END; 

    IF @ScriptMode = 0
    BEGIN   
        update 
            @TrigText 
        set 
            linetext = replace(linetext, 'CREATE TRIGGER', 'ALTER TRIGGER') 
        WHERE 
            upper(left(replace(ltrim(linetext), char(9), ''), 14)) = 'CREATE TRIGGER' 
    END

    insert into @script select '----------------------------------------------'; 
    insert into @script select '-- Creation of Triggers'; 
    insert into @script select ''; 
    insert into @script select ''; 

    DECLARE ms_users CURSOR LOCAL forward_only FOR 
    SELECT 
        T.username, 
        T.objid, 
        MAX(D.lineid) 
    FROM   
        @Triggers T, 
        @TrigText D 
    WHERE  
        T.objid = D.objid 
    GROUP BY    
        T.username, 
        T.objid 
    FOR READ ONLY; 

    OPEN ms_users; 

    FETCH NEXT FROM ms_users INTO @UserName, @ObjID, @MaxID; 

    WHILE @@fetch_status = 0 
    BEGIN 

        insert into @script select 'setuser N''' + @UserName + '''' + CHAR(13) + CHAR(10); 

        insert into @script 
        SELECT 
            '-- Text of the Trigger' = 
            CASE lineid 
                WHEN 1 THEN 'GO' + CHAR(13) + CHAR(10) + linetext 
                WHEN @MaxID THEN linetext + 'GO' 
                ELSE linetext 
            END 
        FROM   
            @TrigText 
        WHERE  
            objid = @ObjID 
        ORDER  
            BY lineid; 

        insert into @script select 'setuser'; 

        FETCH NEXT FROM ms_users INTO @UserName, @ObjID, @MaxID; 
    END; 

    CLOSE ms_users; 

    insert into @script select 'GO'; 
    insert into @script select '------End ------'; 

    DEALLOCATE ms_crs_syscom; 
    DEALLOCATE ms_users; 

    select script from @script order by id

END

Comment l'exécuter:

SET nocount ON 
DECLARE @return_value INT 

EXEC @return_value = [dbo].[SYS_ScriptAllTriggers] @InclDrop = 1 
SELECT 'Return Value' = @return_value 

ALLER

2
user2894913

utiliser syscomments peut ne pas toujours fonctionner. La colonne de texte de syscomments est limitée à 4000 caractères. Un déclencheur supérieur à celui-ci sera tronqué. Vous ne pourrez peut-être pas le voir entièrement.

1
Jude

En fait, si vous examinez la table sys.comments, celle-ci contient un champ colid qui est une colonne numérique; s'il est plus long que le maximum, il aura des nombres> 1. Si vous deviez en sélectionner un avec> 1 colID et copier les deux (s'il y avait 2 enregistrements), vous obtiendrez le déclencheur complet!

0
Patrick Lendrum