2009-11-19 3 views
0

мне нужно выполнить три динамических операторов SQL синхронно на связанный сервер (SQL Server 2005), как это:Выполнение нескольких динамических операторов вместе на связанном сервере

declare @statement nvarchar(max); 

set @statement = 'exec ' + @server_name + '.' + @database_name + '.dbo.Foo;exec ' + @server_name + '.' + @database_name + '.dbo.Bar;exec ' + @server_name + '.' + @database_name + '.dbo.BigTime'; 

exec sp_executesql @statement; 

Чтобы проверить это, у меня есть настройки связанного сервера, ссылки на себя.

При выполнении этого локального (удаляя @server_name), используя SQL Profiler, я вижу, что он выполняется просто отлично, как один оператор. Однако, когда я выполняю это через связанный сервер (используя переменную @server_name), я вижу в SQL Profiler, что каждый оператор запускается отдельно, а sp_reset_connection выполняется после каждого.

Трассировка выглядит примерно так:

Audit Login .... 
exec database.dbo.Foo 
exec sp_reset_connection 
Audit Logout 
Audit Login .... 
exec database.dbo.Bar 
exec sp_reset_connection 
Audit Logout 
Audit Login .... 
exec database.dbo.BigTime 
exec sp_reset_connection 
Audit Logout 

Это вызывает у меня проблемы. Есть ли какие-либо причины, по которым я могу указать SQL Server, чтобы не вызывать sp_reset_connection между операторами?

ответ

0

Можете ли вы сделать один SP на связанном сервере, который вызывает другие 3, а затем просто вызвать его?

Зачем возникает проблема с соединением сброса? Каждый SP использует какое-то особое хранилище постоянного хранения, например, временную таблицу или что-то еще?

+0

Я не могу ничего на связанном сервере изменить. И да, сброс соединения вызывает проблему. –

1

Выполняется три вызова трех связанных серверов, результат - именно то, что вы ожидаете (даже если 3 связанных сервера не отличаются друг от друга). Для того, чтобы достичь того, что описывать, выполнять звонки, как вы описываете: выполнить три процедуры на одном связанном сервере:

linkedserver.master.dbo.sp_ExecuteSQL N' 
    exec dbname.dbo.Foo; 
    exec dbname.dbo.Bar; 
    exec dbname.dbo.BigTime;'; 

Все, что вам нужно сделать, это обернуть это вокруг в динамическом встроенным SQL:

declare @remoteStatement nvarchar(max), @localStatement nvarchar(max); 
set @remoteStatement = N'exec ' + @database_name + N'.dbo.Foo; 
    exec ' + @database_name + N'.dbo.Bar; 
    exec '+ @database_name + N'.dbo.BigTime'; 
set @localStatement = @server_name + N'.master.dbo.sp_executesql @remoteStatement;'; 

exec sp_executesql @localStatement, N'@remoteStatement nvarchar(max)', @remoteStatement; 
+0

Ремус, я написал что-то очень похожее. Однако ваша строка объявления будет бомбить. –

+0

Спасибо Аарон, я исправил его. Служит мне для публикации без проверки синтаксиса ... –

0

Этот могут помочь:

BEGIN DISTRIBUTED TRANSACTION 
your stuff here 
COMMIT TRANSACTION 

Для этого вам понадобится распределенный координатор транзакций.

+0

Это не сработало. Я получаю: «Сервер не смог возобновить транзакцию. Desc: 3500000006». вернулся. Это была хорошая мысль. –

+0

Работает ли MS DTC? –

2
DECLARE @sql1 NVARCHAR(MAX), @sql2 NVARCHAR(MAX); 

SET @sql1 = 'EXEC ' + @database_name + '.dbo.Foo;' 
      + 'EXEC ' + @database_name + '.dbo.Bar;' 
      + 'EXEC ' + @database_name + '.dbo.BigTime;'; 

SET @sql2 = 'EXEC ' + @server_name + '.master.dbo.sp_executeSQL ''' + @sql1 + ''';'; 

EXEC sp_executeSQL @sql2; 
+0

Это master.sys.sp_executesql, кстати. Мне очень понравилась эта идея, но, к моему удивлению, она очень похожа. Используя SQL Profiler, я вижу, что он запускает первый, затем второй, затем запускает sp_executesql со всеми тремя в качестве параметра оператора!?! –

+0

? Кажется, это работает отлично для меня: EXEC master.dbo.sp_executeSQL N'print '' 1 ''; '; ... как для множественных вызовов, на каком сервере вы запускаете профилировщик, тот, кто запускает команды или тот, кто их получает (имя @server_name)? –

+0

Для тестирования я делал все локально.У меня есть связанный сервер, который связывается с самим собой. Мне показалось странным, что выполнение sp_executeSQL на целевом связанном сервере по-прежнему приводило к тому, что каждый оператор разбивался на вызов sp_resetconnection. –

0

Согласно ответу Ремуса, но избегает некоторой динамической SQL с помощью sp_setnetname. YMMV.

Это было предложено в день или 2 назад: Fully qualified table names with SP_ExecuteSql to access remote server

+0

Я не знал о sp_setnetname на самом деле. Является аккуратным трюком, но может быть опасным в параллельной среде, несколько вызывающих могут изменить имя друг на друга и нанести ущерб. –

+0

@remus: Я использовал его как администратор базы данных в ограниченных обстоятельствах, честно говоря, я не думал об этом. Я бы использовал sp_getapplock для управления им – gbn

+0

Я не пытаюсь установить имя сервера в качестве параметра. –

Смежные вопросы