I am trying to execute the below -
DECLARE @SQL nvarchar(max), @LinkServer nvarchar(200), @min INT=1, @max INT
drop table if exists #clients;
create table #clients (Id int identity(1,1), ClientName varchar(200), LinkServer varchar(200));
insert into #clients (ClientName, LinkServer) values ('abc', 'LinkServer1');
insert into #clients (ClientName, LinkServer) values ('xyz', 'LinkServer2');
set @max = (SELECT MAX(Id) FROM #clients)
WHILE(@min<=@max)
BEGIN
@SQL = 'select * from Table;'
SELECT @LinkServer=LinkServer FROM #clients WHERE ID=@min
EXECUTE (@SQL) AT [@LinkServer]
SET @min=@min+1
END
But it reads @LinkServer as a character. I want to run this query on multiple server, but unable to do so with the current syntax. I need to use EXECUTE(@SQL) AT [LinkServer] only.
You can't parameterize the AT linked_server_name
like that, it has to be a literal.
You can do this more easily using a parameterized EXEC
. Not many people know that the procedure name itself can be parameterized. So you just need to build a string Server..sys.sp_executesql
Note that the server name needs to be in a sysname
or nvarchar(128)
, and you need to quote it using QUOTENAME
. Also, don't use WHILE
just to avoid a cursor, it's silly and even more inefficient than a cursor.
DECLARE @proc nvarchar(1000);
DECLARE @crsr CURSOR;
SET @crsr = CURSOR FAST_FORWARD FOR
SELECT procName = QUOTENAME(LinkServer) + '..sys.sp_executesql'
FROM #clients;
OPEN @crsr;
WHILE(1=1)
BEGIN
FETCH NEXT @crsr INTO @proc;
IF @@FETCH_STATUS <> 0
BREAK;
EXEC @proc N'select * from Table;'
END;