Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Curseur SQL Server - boucle sur plusieurs serveurs et exécute la requête

DECLARE @SN VARCHAR(20);

DECLARE C CURSOR LOCAL FAST_FORWARD
  FOR SELECT DISTINCT(SERVERNAME) FROM TABLE 
  where SERVERNAME NOT IN ('SRV1','SRV2','SRV3');

OPEN C;

FETCH NEXT FROM C INTO @SN;
WHILE (@@FETCH_STATUS = 0)
BEGIN 
    PRINT @SN;
    -- you could loop here for each database, if you'd define what that is
    SET @sql = N'SELECT * FROM ' + @SN + '.master.dbo.TABLE;';
    EXEC sys.sp_executesql @sql;
    FETCH NEXT FROM C INTO @SN;
END 
CLOSE C;
DEALLOCATE C;

Modifications :

  1. Il n'y a aucune raison d'utiliser les options de curseur par défaut ici - global, actualisable, dynamique, déroulant, etc. Contexte .

  2. Comme habitude/meilleure pratique, utilisez sp_executesql et non EXEC() . Bien que cela n'ait pas vraiment d'importance dans ce cas, cela peut avoir de l'importance dans d'autres, donc je préférerais toujours coder de la même manière. Contexte .

  3. Veuillez également prendre l'habitude de terminer vos déclarations par des points-virgules. Vous devrez, éventuellement. Contexte .

MODIFIER

Maintenant que nous avons un peu plus d'informations sur vos besoins réels, je vous suggère ce bout de code. Oh, et regardez, pas de curseurs (enfin, pas d'explicite déclarations de curseur et tous les échafaudages qui les accompagnent) !

SET NOCOUNT ON;

DECLARE @dbs TABLE(SERVERNAME SYSNAME, DBNAME SYSNAME);

DECLARE @sql NVARCHAR(MAX) = N'';

-- first, let's get the databases on each server:

SELECT @sql += N'SELECT ''' + SERVERNAME + ''', name FROM '
 + QUOTENAME(SERVERNAME) + '.master.sys.databases
   WHERE database_id > 4 
   AND name NOT IN (N''somedb'',N''someotherdb'');' 
 FROM dbo.INSTALLATION 
   WHERE DATABASETYPE = 'MsSql' 
   AND SERVERNAME IN ('x');

INSERT @dbs EXEC sys.sp_executesql @sql;

SELECT @sql = N'';

-- now, build a command to run in each database context:

SELECT @sql += N'
  EXEC ' + QUOTENAME(SERVERNAME) + '.'
  + QUOTENAME(DBNAME) + '.sys.sp_executesql @sql;'
  FROM @dbs;

-- feel free to change the 3rd parameter here:

EXEC sys.sp_executesql @sql, N'@sql NVARCHAR(MAX)', 
  N'SELECT @@SERVERNAME, DB_NAME(), actual_columns FROM dbo.table_name;';

Cela échouera si table_name n'existe pas, vous aurez donc peut-être encore du travail à faire si vous souhaitez faciliter la gestion des erreurs. Mais cela devrait vous aider à démarrer.

Veuillez également être conscient et utiliser systématiquement le préfixe de schéma. Contexte .