Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Cursor do SQL Server - percorre vários servidores e executa a consulta

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;

Mudanças:

  1. Não há razão para usar as opções de cursor padrão aqui - global, atualizável, dinâmico, rolável etc. Plano de fundo .

  2. Como hábito/prática recomendada, use sp_executesql e não EXEC() . Embora isso realmente não importe neste caso, pode importar em outros, então prefiro sempre codificar da mesma maneira. Plano de fundo .

  3. Além disso, adquira o hábito de terminar suas declarações com ponto e vírgula. Você terá que, eventualmente. Antecedentes .

EDITAR

Agora que temos um pouco mais de informações sobre seus requisitos reais, sugiro este código. Ah, e veja, sem cursores (bem, sem explícito declarações de cursor e todo o andaime que vem com elas)!
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;';

Isso falhará se table_name não existir, então você ainda pode ter algum trabalho a fazer se quiser facilitar o tratamento de erros. Mas isso deve começar.

Além disso, esteja ciente e use consistentemente o prefixo do esquema. fundo .