104 votes

TSQL - Comment utiliser ALLER à l'intérieur de COMMENCER .. FIN de bloc?

Je suis de la génération d'un script automatique de la migration des changements à partir de plusieurs bases de données de développement à la mise en scène ou de la production. Fondamentalement, il faut un tas de modifier les scripts, et les fusionne en un seul script, enveloppant chaque script dans un IF whatever BEGIN ... END déclaration.

Toutefois, certains de ces scripts nécessitent un GO déclaration, de sorte que, par exemple, l'analyseur SQL connaît une nouvelle colonne après sa création.

ALTER TABLE dbo.EMPLOYEE 
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO -- Necessary, or next line will generate "Unknown column:  EMP_IS_ADMIN"
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever

Cependant, une fois que je l'envelopper dans une IF bloc:

IF whatever
BEGIN
    ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
    GO
    UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
END

Il échoue parce que je suis l'envoi d'un BEGIN avec l'absence de correspondance END. Cependant, si je supprime l' GO il se plaint de nouveau sur une colonne inconnues.

Est-il possible de créer et de mettre à jour la même colonne au sein d'un seul IF bloc?

45voto

Oded Points 271275

GO n'est pas SQL - il est tout simplement un lot de séparateur utilisé dans certains MS SQL outils.

Si vous ne vous en servez pas, vous devez vous assurer que les instructions sont exécutées séparément, soit dans les différents lots ou à l'aide de SQL dynamique pour la population (merci @gbn):

IF whatever
BEGIN
    ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL;

    EXEC ('UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever')
END

18voto

mellamokb Points 34067

Vous pourriez essayer d' sp_executesql, le fractionnement du contenu entre chaque GO déclaration séparée en une chaîne de caractères à être exécuté, comme le montre l'exemple ci-dessous. Aussi, il y a un @statementNo variable pour suivre l'instruction qui est en cours d'exécution pour faciliter le débogage où une exception s'est produite. Les numéros de ligne sera par rapport au début de la déclaration pertinente nombre qui a provoqué l'erreur.

BEGIN TRAN

DECLARE @statementNo INT
BEGIN TRY
    IF 1=1
    BEGIN
        SET @statementNo = 1
        EXEC sp_executesql
            N'  ALTER TABLE dbo.EMPLOYEE
                    ADD COLUMN EMP_IS_ADMIN BIT NOT NULL'

        SET @statementNo = 2
        EXEC sp_executesql
            N'  UPDATE dbo.EMPLOYEE
                    SET EMP_IS_ADMIN = 1'

        SET @statementNo = 3
        EXEC sp_executesql
            N'  UPDATE dbo.EMPLOYEE
                    SET EMP_IS_ADMIN = 1x'
    END
END TRY
BEGIN CATCH
    PRINT 'Error occurred on line ' + cast(ERROR_LINE() as varchar(10)) 
       + ' of ' + 'statement # ' + cast(@statementNo as varchar(10)) 
       + ': ' + ERROR_MESSAGE()
    -- error occurred, so rollback the transaction
    ROLLBACK
END CATCH
-- if we were successful, we should still have a transaction, so commit it
IF @@TRANCOUNT > 0
    COMMIT

Vous pouvez également facilement exécuter des multi-instructions de ligne, comme illustré dans l'exemple ci-dessus, simplement en les enveloppant dans des guillemets simples ('). N'oubliez pas d'échapper les guillemets simples contenues à l'intérieur de la chaîne avec un double guillemet simple ('') lors de la création de scripts.

11voto

Andy Joiner Points 747

Vous pouvez joindre les déclarations de début et de FIN au lieu d'ALLER inbetween

IF COL_LENGTH('Employees','EMP_IS_ADMIN') IS NULL --Column does not exist
BEGIN
    BEGIN
        ALTER TABLE dbo.Employees ADD EMP_IS_ADMIN BIT
    END

    BEGIN
        UPDATE EMPLOYEES SET EMP_IS_ADMIN = 0
    END
END

(Testé sur la base de données Northwind)

9voto

J'ai finalement réussi à le faire fonctionner en remplaçant chaque occurrence de GO sur sa propre ligne avec

END
GO

---Automatic replacement of GO keyword, need to recheck IF conditional:
IF whatever
BEGIN

C'est grandement préférable d'emballer chaque groupe des états d'une chaîne, mais est encore loin d'être idéale. Si quelqu'un trouve une meilleure solution, post et je vais l'accepter à la place.

-1voto

jim a Points 19

Vous pouvez incorporer un GOTO et LABEL des déclarations de sauter sur le code, laissant ainsi l' GO mots-clés intacte.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X