2016-08-15 4 views
1

Я пытаюсь использовать функцию связанного сервера в SQL Server (2014) для выполнения кросс-серверного запроса (вычисления) из хранимой процедуры.SQL Server Linked Server Queries w/ANSI_WARNINGS OFF

Хранимая процедура была первоначально разработана для выполнения локального запроса (вычисления) с использованием динамического T-SQL (через sp_executeSQL). Выражение генерируется нашим приложением и может быть любым арифметическим выражением.

Простой пример (A/B) запрос реализован как:

(dynamic sql) 
SELECT f1.Value/f2.Value 
FROM dbo.DimDate d 
INNER JOIN 
dbo.vAverageData f1 ON f1.ParentID=x and f1.TimeStamp = d.TimeStamp 
INNER JOIN 
dbo.vAverageData f2 ON f2.ParentID=y f2.TimeStamp = d.TimeStamp 
WHERE d.TimeStamp BETWEEN @StartDateTime AND @EndDateTime 

Теперь это становится интересным в том, что ни один из расчета выражений проверки для обработки или условий, таких как деление на ноль. Вместо этого, оригинальный разработчик решил выпустить два заявления, прежде чем любой из динамического T-SQL выполняется:

SET ANSI_WARNINGS OFF 
SET ARITHABORT OFF 

Это хорошо работало в течение многих лет, пока в один прекрасный день кто-то спросил нас, если мы могли бы выполнять перекрестные запросы сервера. Естественно, первым вариантом, который появился у меня в голове, было реализовать (1) соединение связанного сервера между двумя серверами и (2) изменить динамический код генерации T-SQL (в нашем приложении), чтобы префикс каждого объекта с именем связанного сервера и имя базы данных.

В приведенном выше примере будет преобразована в нечто вроде:

(dynamic sql) 
SELECT f1.Value/f2.Value 
FROM dbo.DimDate d 
INNER JOIN 
dbo.vAverageData f1 ON f1.ParentID=x and f1.TimeStamp = d.TimeStamp 
INNER JOIN 
*<LinkedServer>.<RemoteDatabase>*.dbo.vAverageData f2 ON f2.ParentID=y f2.TimeStamp = d.TimeStamp 
WHERE d.TimeStamp BETWEEN @StartDateTime AND @EndDateTime 

В первый раз, я пытался запустить одну из этих перекрестных запросов сервера, я получил позорные:

«Гетерогенные запросы для этого необходимо установить параметры ANSI_NULLS и ANSI_WARNINGS . Это обеспечивает согласованный запрос семантики . Включите эти параметры, а затем переиздайте свой запрос. "

Очевидно, что проще всего было бы удалить упомянутые выше звонки SET. Однако в нашем случае они служат цели и предотвращают прерывание запроса/транзакции в случае деления на ноль, переполнения и т. Д.

На этом этапе (без основной перезаписи) предположим, что мы должны иметь эти SET на месте ...

Есть ли что-нибудь, что я могу сделать, чтобы сделать эту работу без удаления вызовов SET? Существуют ли какие-либо настройки на удаленном сервере/базе данных, которые можно установить? Как насчет связанного объекта сервера?

Я не пробовал, но есть свойства базы данных для ANSI Warnings Enabled и т. Д. Будет ли это исправлено, если оно будет установлено последовательно в обеих базах данных? Это плохая/опасная практика?

enter image description here

Оба сервера точно такая же версия SQL Server (2014) и обе базы данных содержат наш код, то есть мы можем изменить все, что угодно.

+0

Можете ли вы попробовать открыть набор строк и посмотреть, работает ли это, я не пробовал, но всего лишь выстрел – TheGameiswar

+0

Отличная идея, но я попытался что-то сделать с помощью INNER JOIN OPENROWSET ('SQLNCLI', 'SERVER = xxx; UID = yyy; PWD = zzz; ',' SELECT * FROM vAverageData WHERE ParentID = a '), но я все еще получаю ту же ошибку. –

+0

Кажется, что заданные параметры должны быть истинными в соответствии с этим, и кажется, что они включены на разных уровнях: https: //technet.microsoft.com/en-us/library/ms175088 (v = sql.105) .aspx – TheGameiswar

ответ

2

Независимо от типа связанного сервера, нет никакого способа обойти его в BOL, найденном here.

соединение должно иметь ANSI_NULLS и опцию ANSI_WARNINGS установленного ON перед подключением может выполнять распределенные запросы.Для получения дополнительной информации см SET ANSI_DEFAULTS (Transact-SQL)

Один из способов это сделать, чтобы изменить запрос, добавив операторы, как показано ниже. Сделав локальную копию удаленной таблицы, вы можете свести к минимуму использование параметров, которые вам не нужны, и свести к минимуму изменения в другом месте.

SET ANSI_WARNINGS ON; 

SELECT Columns_Used_For_Query INTO #Temporary_Table 
FROM Remote_Table 
WHERE Search_Condition; 

SET ANSI_WARNINGS OFF; 

--Do other stuff 

Это может быть не лучшее решение с точки зрения производительности, особенно если правильный показатель имеет решающее значение. Но это ваше испытание.

На стороне примечания, если вы все еще получаете то же сообщение об ошибке, то это, скорее всего, означает, что хранимая процедура была создана с помощью ANSI_NULLS OFF, и в этом случае вам нужно будет включить эту опцию тогда ALTER. Сохраненная процедура запоминает настройки ANSI_NULLS и QUOTED_IDENTIFIER во время создания и изменения.

+0

Отличный подход. Я ценю вход. –

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