Comment exécuter SQL sur tous les DB sur un serveur

38

J'ai un SQL standard que je lance sur plusieurs bases de données sur un seul serveur pour m'aider à diagnostiquer les problèmes:

select 
    so.name,
    so.type,
    MAX(case when sc.text like '%remote%' then '' ELSE 'N' END) AS Relevant,
    @@ServerName as Server,
    DB_Name() as DBName 
from
    sysobjects so with (nolock)
    join syscomments sc with (nolock) on so.id = sc.id
where (sc.text like '%emote%')
group by so.name, so.type
order by so.type, so.name

Comment puis-je l'exécuter sur toutes les bases de données sur un seul serveur? (en plus de se connecter manuellement à un à la fois et de l'exécuter)

Andrew Bickerton
la source
Vous pouvez également trouver cette alternative de ms_foreachdb utile.
Nomade

Réponses:

44

sp_MSForEachDB

Une option est sp_MSForEachDB . C'est non documenté mais néanmoins utile

DECLARE @command varchar(1000) 
SELECT @command = 
    'USE [?] UPDATE Table1 SET Field1 = ''ninjas'' WHERE Field2 = ''pirates''' 
EXEC sp_MSforeachdb @command

Une recherche sur les interwebs a beaucoup d'autres exemples aussi

Note: Étant une fonction non supportée (qui a quelques bugs connus), vous voudrez peut-être écrire votre propre version (merci @Pradeep)


L'exemple SQL ci-dessus devrait être restructuré comme suit:

DECLARE @findKeySQL nvarchar(2000)
DECLARE @searchKey nvarchar(20)

SET @searchKey = lower('%remote%')

SET @findKeySQL = 'IF ''[?]'' NOT IN (''[master]'', ''[model]'', 
                                     ''[msdb]'', ''[tempdb]'')
        select 
            so.name,
            so.type,
            @@ServerName as Server,
            ''?'' as DBName 
        from
            [?].dbo.sysobjects so with (nolock)
            join [?].sys.all_sql_modules sc with (nolock) on so.id = sc.object_id
        where (lower(sc.definition) like ''' + @searchKey + ''')
        group by so.name, so.type
        order by so.type, so.name'

EXEC sp_MSForEachDB @findKeySQL

REMARQUES:

  1. ? est remplacé dans la requête par le nom de la base de données, donc structurez la requête pour définir explicitement la base de données sur laquelle elle doit interroger
  2. modifié pour utiliser sys.all_sql_modules en tant que texte complet du module (syscomments peut scinder le mot clé lorsque les lignes sont étendues )
gbn
la source
sp_MSforeachdb peut parfois être floconneux, alors consultez le lien fourni dans la réponse de Pradeep.
Eric Humphrey - lotsahelp
Le sp_MSForEachDB semble bon pour une requête rapide. Existe-t-il un moyen de montrer à quelle base de données chaque résultat provient?
Diskdrive
@Diskdrive: ajoute , ''?'' AS DBNameà n'importe quelle instruction select. Selon mon exemple
gbn le
9

Juste mon $ 0,05: SQL Multi Script (exécution de plusieurs scripts sur plusieurs serveurs SQL).

garik
la source
1
Des réponses comme celle-ci, approuvant une solution commerciale, devraient être interdites SO!
Fandango68
2
@ Fandango68 Je ne travaille pas pour cette entreprise. Je viens d'utiliser tellement outil. Pas de conflit d'intérêts, et vous? ).
Garik
4
@ Fandango68 Je préférerais qu'ils ne le soient pas. Les meilleures solutions doivent toujours être considérées, et les meilleures solutions libres comparées à celles-ci.
Paul
2

Il existe une autre méthode permettant d'obtenir une sortie dans un seul jeu de résultats semi-fusionné. Commencez par ouvrir les serveurs enregistrés et créez un nouveau groupe sous Groupes de serveurs locaux, puis enregistrez votre serveur une fois pour chaque base de données, en définissant dans chaque cas la base de données par défaut comme celle souhaitée.

Une fois terminé, cliquez avec le bouton droit sur votre groupe et sélectionnez Nouvelle requête. La fenêtre de requête qui s'ouvre aura "plusieurs" où vous verrez normalement un nom de serveur sur la barre d'état. Toutes les requêtes exécutées dans cette fenêtre fonctionneront sur chaque serveur enregistré qui faisait partie du groupe. La première colonne des résultats sera le nom du serveur enregistré. L'ensemble de résultats sera fragmenté par cette première colonne et l'ordre par testaments ne fonctionnera que dans ce fragment.

Fonctionnalité très puissante mais négligée lorsque vous devez régulièrement exécuter le même code SQL sur plusieurs serveurs.

Paul
la source
J'utilise beaucoup cela et c'est une fonctionnalité intéressante dans SSMS. L'inconvénient est que c'est pour une utilisation manuelle seulement, donc inutile si vous voulez automatiser quelque chose à exécuter régulièrement.
Monsieur jure beaucoup le
1

Ma société a développé un outil appelé xSQL Script Executor . C'est gratuit pour un usage personnel, et pour moi, le déploiement de scripts sur plusieurs cibles est très facile.

Endi Zhupani
la source
C'est un bon programme! Facile à utiliser et intuitif.
Sean Perkins
0

J'ai développé cet outil: https://github.com/andreujuanc/TakoDeploy

Je suis encore en train d'écrire quelques lignes dessus, mais c'est assez stable maintenant. Je l'ai utilisé contre des bases de données de production et fonctionne à merveille.

Juan Carlos
la source