Archives du mot-clé Boucle sur chaque base

SQL Server – Sp_MSForEachDB une façon simple de requêter toutes les bases de données d’une instance

De temps en temps il est nécessaire d’exécuter une requête simple sur toute les bases de données d’une instance SQL Server.

Jusqu’à il n’y a pas très longtemps j’ai toujours écrit des requêtes très complexes qui utilisé des CURSOR et des tables temporaires afin d’effectuer le travail voulu.

Et après j’ai trouvé la procédure stockée non-documentée Sp_MSForEachDB.

Pour expliquer simplement : cette procédure stockée laisse l’utilisateur coller un variable ? dans une requête qui prend la place de la base de données et elle exécute la même requête pour chaque base attachée à l’instance SQL Server.

Voici une petite requête pour montrer comment ça fonctionne :

EXEC sys.sp_MSforeachdb 'USE ?;
SELECT DB_ID(), DB_NAME()'

Vous devriez voir une like de toute les bases de données attachées à votre instance par identifiant et nom.

Vous allez voir que le moteur retourne plusieurs jeux de résultats dans le fenêtre SSMS. C’est à cause du fait que sp_MSforeachdb itère sur chaque base. Ce n’est pas une transaction unique.

Pour l’utilisateur avancé qui aimerait industrialiser l’utilité de cette procédure stockée vous pouvez simplement créer une table temporaire qui stocke les résultats et ensuite vous allez pouvoir requête sur cette table à peu plus loin dans le code T-SQL.

Voici un exemple que j’ai utilisé pour contrôler le taux de fragmentation de toutes les indexes fragmentés de plus que 5%:

CREATE TABLE dbo.#FragTab
(DB_Name VARCHAR(100),
[Schema] VARCHAR(50),
[TABLE] VARCHAR(200),
[INDEX] VARCHAR(200),
avg_fragmentation_in_percent FLOAT,
REBUILD_Necessary BIT,
REORGANISE_Necessary BIT)

EXEC sys.sp_MSforeachdb
'
USE ?;
INSERT INTO #FragTab
SELECT
DBs.name as '
'DB_Name'',
dbschemas.[name] as '
'Schema'',
dbtables.[name] as '
'Table'',
dbindexes.[name] as '
'Index'',
indexstats.avg_fragmentation_in_percent,
CASE WHEN indexstats.avg_fragmentation_in_percent > 30 THEN 1 ELSE 0 END as REBUILD_Necessary,
CASE WHEN indexstats.avg_fragmentation_in_percent BETWEEN 5 AND 30 THEN 1 ELSE 0 END as REORGANISE_Necessary
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
AND indexstats.index_id = dbindexes.index_id
LEFT OUTER JOIN sys.databases as DBs ON DBs.database_id = indexstats.database_id
WHERE indexstats.database_id = DB_ID()
AND indexstats.avg_fragmentation_in_percent > 5
AND dbindexes.name IS NOT NULL'


SELECT * FROM #FragTab
DROP TABLE #FragTab