sql >> Base de Datos >  >> RDS >> Sqlserver

Cursor de SQL Server:recorra varios servidores y ejecute la 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;

Cambios:

  1. No hay ninguna razón para usar las opciones de cursor predeterminadas aquí:global, actualizable, dinámico, desplazable, etc. Fondo .

  2. Como hábito/mejor práctica, use sp_executesql y no EXEC() . Si bien en realidad no importa en este caso, puede importar en otros, por lo que prefiero codificar siempre de la misma manera. Antecedentes .

  3. Además, adquiera el hábito de terminar sus declaraciones con punto y coma. Tendrás que hacerlo, eventualmente. Antecedentes .

EDITAR

Ahora que tenemos un poco más de información sobre sus requisitos reales, sugiero este fragmento de código. Ah, y mira, sin cursores (bueno, sin explícito declaraciones de cursor y todo el andamiaje que viene con ellas)!

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

Esto fallará si table_name no existe, por lo que es posible que aún tenga trabajo por hacer si desea facilitar el manejo de errores. Pero esto debería ayudarte a empezar.

Además, tenga en cuenta y utilice de forma coherente el prefijo de esquema. Antecedentes .