sql >> Databasteknik >  >> RDS >> Sqlserver

SQL Server-markör - gå igenom flera servrar och kör en fråga

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;

Ändringar:

  1. Det finns ingen anledning att använda standardmarköralternativen här - globala, uppdateringsbara, dynamiska, rullningsbara, etc. Bakgrund .

  2. Som en vana/bästa praxis, använd sp_executesql och inte EXEC() . Även om det inte spelar någon roll i det här fallet, kan det spela roll i andra, så jag föredrar att alltid koda på samma sätt. Bakgrund .

  3. Ta också för vana att avsluta dina uttalanden med semikolon. Du måste till slut. Bakgrund .

REDIGERA

Nu när vi har lite mer information om dina faktiska krav föreslår jag denna kodbit. Åh, och se, inga markörer (nåja, inga explicita). markördeklarationer och alla ställningar som följer med dem)!

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

Detta kommer att misslyckas om tabellnamn inte finns, så du kan fortfarande ha en del att göra om du vill underlätta felhanteringen. Men det här borde få dig igång.

Var också medveten om och använd konsekvent schemaprefixet. Bakgrund .




  1. Gå med i en kolumn med SELECT-fråga i PostgreSQL

  2. Hur kan jag få byte[] från bytea-kolumnen med MyBatis?

  3. Skenor med Postgres-data returneras ur funktion

  4. Fyll i flera tabeller från ett enda JSON-objekt med json_populate_recordset