Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Kursor SQL Server - pętla przez wiele serwerów i wykonanie zapytania

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;

Zmiany:

  1. Nie ma powodu, aby używać tutaj domyślnych opcji kursora — globalnych, aktualizowalnych, dynamicznych, przewijalnych itp. Tło .

  2. Jako nawyk / najlepsza praktyka, użyj sp_executesql a nie EXEC() . Chociaż w tym przypadku nie ma to większego znaczenia, może mieć znaczenie w innych, więc wolałbym zawsze kodować w ten sam sposób. Tło .

  3. Prosimy również o wyrobienie sobie nawyku kończenia wypowiedzi średnikami. W końcu będziesz musiał. Tło .

EDYTUJ

Teraz, gdy mamy trochę więcej informacji o twoich rzeczywistych wymaganiach, sugeruję ten fragment kodu. Aha, i spójrz, żadnych kursorów (no cóż, żadnych jasnych) deklaracje kursora i całe rusztowanie, które się z nimi wiąże)!

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

To się nie powiedzie, jeśli nazwa_tabeli nie istnieje, więc nadal możesz mieć trochę pracy do wykonania, jeśli chcesz ułatwić obsługę błędów. Ale to powinno Cię zacząć.

Należy również pamiętać o prefiksie schematu i konsekwentnie go używać. Tło .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wygenerować skrypt wstawiania dla wybranych rekordów?

  2. Bootstrapowanie SQL Express z WiX?

  3. Przeczytaj plik dziennika (*.LDF) w SQL Server 2008

  4. połącz dwie kolumny bazy danych w jedną kolumnę wyników;

  5. Rozwiązywanie problemów z długimi zapytaniami w MS SQL Server