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;
変更点:
-
ここでデフォルトのカーソルオプション(グローバル、更新可能、動的、スクロール可能など)を使用する理由はありません。背景 。
-
習慣/ベストプラクティスとして、
sp_executesql
を使用しますEXEC()
ではありません 。この場合は実際には問題ではありませんが、他の場合は問題になる可能性があるため、常に同じ方法でコーディングすることをお勧めします。 背景 。 -
また、ステートメントをセミコロンで終了する習慣を身に付けてください。最終的にはそうする必要があります。 背景 。
編集
実際の要件についてもう少し情報が得られたので、このコードをお勧めします。ああ、見てください、カーソルはありません(まあ、明示的はありません カーソル宣言とそれに付随するすべてのスキャフォールド)!
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;';
table_nameが存在しない場合、これは失敗するため、エラー処理を容易にしたい場合は、まだやるべきことがいくつかあるかもしれません。しかし、これで始められるはずです。
また、スキーマプレフィックスを意識し、一貫して使用してください。 背景 。