web-dev-qa-db-fra.com

Transact SQL pour exécuter un autre script Transact SQL

J'ai 10 scripts SQL de transaction qui créent chacun une table et la remplissent de données.

J'essaie de créer 1 script SQL maître qui exécutera chacun des 10 autres scripts.

Existe-t-il un moyen avec TSQL/TRANSACTSQL pour Microsoft SQL Server 2008 d'exécuter un autre script tsql à partir du script tsql actuel?

Il est destiné à être exécuté via SQL Server Management Studio (SSMS).

Merci!

56
Steve Stedman

Essayez ceci si vous essayez d'exécuter un fichier .sql dans SSMS:

:r C:\Scripts\Script1.sql
:r C:\Scripts\Script2.sql
:r C:\Scripts\Script3.sql
...

remarque: pour que cela s'exécute, activez le mode de commande sql (Requête> Mode SQLCMD)

Si ce sont des scripts que vous exécutez assez souvent, vous pourriez envisager de les déposer dans un proc stocké et de les exécuter de cette façon ...

Vous pouvez également le faire via sqlcmd (qui, je crois, est plus courant):

sqlcmd -S serverName\instanceName -i C:\Scripts\Script1.sql
92
Abe Miessler

Le moyen le plus simple serait de faire de vos scripts des procédures stockées et d'appeler (via la commande EXECUTE) chaque procédure tour à tour à partir d'une procédure centrale. C'est idéal si vous allez exécuter le même ou les mêmes scripts encore et encore (ou le même script avec des paramètres différents transmis).

Si vos scripts sont des fichiers .sql (ou tout autre type de texte), comme @Abe Miesller le dit (vote positif), vous pouvez les exécuter à partir de SSMS via la commande: r, lorsque le mode SQLCMD est activé. Vous devez connaître et écrire le chemin et le nom exacts du fichier. Cela ne peut pas être fait à partir d'une procédure stockée.

Une dernière alternative, utilisable avec des noms de fichiers "connus" et nécessaire pour des noms de fichiers arbitraires (par exemple, tous les fichiers actuellement chargés dans un sous-dossier) est de tirer parti de la puissance de la procédure étendue XP_CMDSHELL. De telles solutions peuvent obtenir un compelx assez rapidement (utilisez-le pour récupérer la liste des fichiers, construire et exécuter via xp_cmdshell une chaîne appelant SQLCMD pour chaque fichier à son tour, gérer les résultats et les erreurs via les fichiers de sortie, ça continue), donc je ne ferais que faites cela en dernier recours.

5
Philip Kelley

Vous pouvez utiliser osql ou mieux encore le nouveau sqlcmd presque de manière interchangeable. J'utilise osql dans cet exemple uniquement parce que je me trouvais avoir un échantillon de code, mais en production, j'utilise sqlcmd. Voici un extrait de code d'une procédure plus large que j'utilise pour exécuter des scripts de mise à jour sur des bases de données. Ils sont classés par version majeure, mineure, version, comme je nomme mes scripts en utilisant cette convention pour suivre les versions. Vous manquez évidemment tous mes messages d'erreur, les parties où je tire les scripts disponibles de la base de données, les variables de configuration, etc. mais vous pouvez toujours trouver cet extrait utile.

La partie principale que j'aime à propos d'osql ou sqlcmd est que vous pouvez exécuter ce code dans ssms, ou dans une procédure stockée (appelée sur une base planifiée peut-être) ou à partir d'un fichier batch. Très souple.

--Use cursor to run upgrade scripts
DECLARE OSQL_cursor CURSOR
READ_ONLY
FOR SELECT FileName 
FROM #Scripts
ORDER BY Major, Minor, Release, Build

OPEN OSQL_cursor

FETCH NEXT FROM OSQL_cursor INTO @name
WHILE (@@fetch_status <> -1)
BEGIN
    IF ((@@fetch_status <> -2) AND (@result = 0))
    BEGIN
        SET @CommandString = 'osql -S ' + @@ServerName + ' -E -n -b -d ' + @DbName + ' -i "' + @Dir + @name + '"'
        EXEC @result = master.dbo.xp_cmdshell @CommandString, NO_OUTPUT
        IF (@result = 0)
        BEGIN
            SET @Seconds = DATEDIFF(s, @LastTime, GETDATE())
            SET @Minutes = @Seconds / 60
            SET @Seconds = @Seconds - (@Minutes * 60)
            PRINT 'Successfully applied ' + @name + ' in ' + cast(@Minutes as varchar) 
                + ' minutes ' + cast(@Seconds as varchar) + ' seconds.'
            SET @LastTime = GETDATE()
        END
        ELSE
        BEGIN
            SET @errMessage = 'Error applying ' + @name + '! The database is in an unknown state and the schema may not match the version.'
            SET @errMessage = @errMessage + char(13) + 'To find the error restore the database to version ' + @StartingVersion
            SET @errMessage = @errMessage + ', set @UpToVersion = the last version successfully applied, then run ' + @name
            SET @errMessage = @errMessage + ' manually in Query Analyzer.'  
        END
        IF @name = (@UpToVersion + '.sql')
            GOTO CleanUpCursor --Quit if the final script specified has been run.
    END
    FETCH ENDT FROM OSQL_cursor INTO @name
END
5
Shane Delmore

Ou utilisez simplement openrowset pour lire votre script dans une variable et l'exécuter:

DECLARE @SQL varchar(MAX)
SELECT @SQL = BulkColumn
FROM OPENROWSET
    (   BULK 'MeinPfad\MeinSkript.sql'
    ,   SINGLE_BLOB ) AS MYTABLE

--PRINT @sql
EXEC (@sql)
5
Pesche Helfer

En supposant que vous souhaitez conserver les 10 scripts dans leurs propres fichiers individuels, je dirais que la façon la plus simple de faire ce que vous voulez serait de créer un fichier de commandes qui exécute osql.exe pour exécuter les 10 scripts dans l'ordre que vous souhaitez.

2
Russell McClure