sql >> Database >  >> RDS >> Sqlserver

SQL Server-cursor - loop door meerdere servers en voer query uit

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;

Wijzigingen:

  1. Er is geen reden om hier de standaard cursoropties te gebruiken - globaal, bijwerkbaar, dynamisch, schuifbaar, enz. Achtergrond .

  2. Gebruik als gewoonte / best practice sp_executesql en niet EXEC() . Hoewel het in dit geval niet echt uitmaakt, kan het er in anderen toe doen, dus ik zou er de voorkeur aan geven altijd op dezelfde manier te coderen. Achtergrond .

  3. Maak er ook een gewoonte van om uw uitspraken te beëindigen met puntkomma's. Je zult uiteindelijk wel moeten. Achtergrond .

BEWERKEN

Nu we wat meer informatie hebben over uw werkelijke vereisten, raad ik u dit stukje code aan. Oh, en kijk, geen cursors (nou ja, geen expliciete cursorverklaringen en alle bijbehorende steigers)!

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

Dit zal mislukken als table_name niet bestaat, dus je hebt misschien nog wat werk te doen als je de foutafhandeling wilt vergemakkelijken. Maar dit zou je op weg moeten helpen.

Houd ook rekening met het schemavoorvoegsel en gebruik het consequent. Achtergrond .




  1. Verbindingsverwerking en -beperking met ProxySQL

  2. Krijg alle POST-gegevens en stuur een e-mail

  3. Hoe moet ik omgaan met dubbele invoergewichten in de MyISAM-zoekindex?

  4. Wat is de JDBC-tegenhanger van het \connect-commando van Postgres?