我有以下代码(光标):
DECLARE @SN VARCHAR(20);
DECLARE @sql NVARCHAR(MAX);
DECLARE C CURSOR LOCAL FAST_FORWARD
FOR SELECT DISTINCT(SERVERNAME) FROM INSTALLATION
where DATABASETYPE = 'MsSql' AND SERVERNAME IN ('x');
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
SELECT name
FROM master.dbo.sysdatabases
WHERE name not in ('master','model','msdb','tempdb');
SET @sql = N'SELECT TOP 1 NAME FROM TABLE ';
EXEC sp_executesql @sql;
FETCH NEXT FROM C INTO @SN;
END
CLOSE C;
DEALLOCATE C;
我希望能够遍历每个服务器,并在某些(不是全部)数据库上执行select语句。
查询类似于:
SELECT TOP 1 NAME FROM TABLE
我运行游标的服务器将所有其他服务器作为链接服务器。
答案 0 :(得分:6)
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;
的变化:
此处没有理由使用默认光标选项 - 全局,可更新,动态,可滚动等。Background。
作为习惯/最佳做法,请使用sp_executesql
而非EXEC()
。虽然在这种情况下它并不重要,但在其他情况下它可能很重要,所以我更喜欢始终以相同的方式编码。 Background
此外,请养成用分号终止你的陈述的习惯。你最终必须这样做。 Background
修改强>
现在我们有关于您实际需求的更多信息,我建议这段代码。哦,看,没有游标(好吧,没有显式的游标声明和随附的所有脚手架)!
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不存在,则会失败,因此如果您希望简化错误处理,可能还需要做一些工作。但这应该让你开始。
另外,请注意并始终使用模式前缀。 Background