Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server-Cursor - Schleife durch mehrere Server und Ausführung der Abfrage

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;

Änderungen:

  1. Es gibt keinen Grund, hier die standardmäßigen Cursoroptionen zu verwenden – global, aktualisierbar, dynamisch, scrollbar usw. Hintergrund .

  2. Verwenden Sie als Gewohnheit/Best Practice sp_executesql und nicht EXEC() . Während es in diesem Fall nicht wirklich wichtig ist, kann es in anderen Fällen wichtig sein, also würde ich es vorziehen, immer auf die gleiche Weise zu codieren. Hintergrund .

  3. Gewöhnen Sie sich außerdem an, Ihre Aussagen mit Semikolons abzuschließen. Irgendwann wirst du es müssen. Hintergrund .

BEARBEITEN

Jetzt, da wir ein wenig mehr Informationen über Ihre tatsächlichen Anforderungen haben, schlage ich diesen Code vor. Oh, und siehe da, keine Cursor (na ja, keine expliziten Cursor-Deklarationen und alle damit verbundenen Gerüste)!

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

Dies schlägt fehl, wenn table_name nicht vorhanden ist, sodass Sie möglicherweise noch etwas zu tun haben, wenn Sie die Fehlerbehandlung erleichtern möchten. Aber das sollte Ihnen den Einstieg erleichtern.

Bitte achten Sie auch auf das Schema-Präfix und verwenden Sie es konsequent. Hintergrund .