Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Cursore di SQL Server:scorre più server ed esegue query

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;

Modifiche:

  1. Non vi è alcun motivo per utilizzare le opzioni predefinite del cursore qui:globale, aggiornabile, dinamico, scorrevole, ecc. Sfondo .

  2. Come abitudine/migliore pratica, usa sp_executesql e non EXEC() . Anche se non ha molta importanza in questo caso, può avere importanza in altri, quindi preferirei codificare sempre allo stesso modo. Sfondo .

  3. Inoltre, prendi l'abitudine di terminare le tue affermazioni con punto e virgola. Dovrai, alla fine. Sfondo .

MODIFICA

Ora che abbiamo un po' più di informazioni sui tuoi reali requisiti, ti suggerisco questo pezzo di codice. Oh, e guarda, niente cursori (beh, niente esplicito dichiarazioni del cursore e tutto lo scaffolding che ne deriva)!

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;';

Questo fallirà se nome_tabella non esiste, quindi potresti avere ancora del lavoro da fare se vuoi facilitare la gestione degli errori. Ma questo dovrebbe iniziare.

Inoltre, sii consapevole e utilizza costantemente il prefisso dello schema. Sfondo .