Ответ 1
Пробовали ли вы эту вариацию - в основном вы нажимаете вызов функции, которая должна выполняться локально в удаленном поле:
EXEC REMOTE_SERVER_NAME.db_name..sp_executesql N'SELECT *
FROM dbo.MyTableValuedFunctionName();';
У меня был запрос с набором параметров, которые нужно было запускать несколько раз с разными параметрами, поэтому я завернул его в функцию, учитывающую таблицу.
Эта функция, требуемая для таблицы, должна быть вызвана с удаленного сервера. К сожалению, вызов сбоя на связанном сервере с ошибкой:
Msg 4122, Level 16, State 1, Line 29
Remote table-valued function calls are not allowed.
Microsoft признала, что "вызов функции, ориентированной на таблицу удаленно", является функцией, отсутствующей в SQL Server 2008. См. http://connect.microsoft.com/SQLServer/feedback/details/276758/remote-table-valued-function-calls-are-not-allowed
Я обнаружил обходной путь с использованием синтаксиса OPENQUERY, который позволяет запросу запускать локально на удаленном сервере и затем возвращать набор результатов. См.: http://social.msdn.microsoft.com/Forums/en/transactsql/thread/7a6e4aa1-630b-4ad5-aee5-15139987adbd
К сожалению, это обходное решение требует обходного пути, поскольку для него требуется строка в качестве аргумента, то есть вы не можете передавать переменную, используя синтаксис OPENQUERY, и вы даже не можете конкатенировать в ней строку, например, если вы хотите включить переменные, которые вы хотите передать удаленной табличной функции. Обходной путь для обходного пути заключается в явном построении запроса OPENQUERY с динамическим SQL, обеспечивающего передачу нормальной строки. См.: http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/0847ad24-0dfe-4ae1-9788-5516c7830f40/
Тем не менее, из этого вытекает другая проблема. Даже после того, как все кавычки и двойные кавычки и четверные кавычки встроены правильно, так что вся вещь может быть передана через exec sp_executesql, все еще есть проблема:
Когда запрос в конечном итоге вызывает функцию таблицы, я получаю ошибку:
OLE DB provider "SQLNCLI10" for linked server "MY_REMOTE_SERVER_NAME" returned message "Deferred prepare could not be completed.".
Msg 7416, Level 16, State 1, Procedure MyTableValuedFunctionName, Line 22
Access to the remote server is denied because no login-mapping exists.
Я не уверен, почему я получаю эту ошибку, потому что отображение существует для моего имени пользователя, и если я просто заменю табличную функцию фактической таблицей, она вернет результаты. Проблема возникает с оператором OPENQUERY, независимо от того, выполнялась ли она с помощью sp_executesql или нет, и, как я уже сказал, это происходит только при вызове табличной функции.
Есть идеи, как это решить?
Пробовали ли вы эту вариацию - в основном вы нажимаете вызов функции, которая должна выполняться локально в удаленном поле:
EXEC REMOTE_SERVER_NAME.db_name..sp_executesql N'SELECT *
FROM dbo.MyTableValuedFunctionName();';
Если вы не можете решить проблему, вызвав EXEC (потому что вы вызываете эту функцию из другой функции или пытаетесь сделать что-то вроде INSERT EXEC, но вы не можете ее вложить и т.д.), здесь это рабочий стол, который решил эту проблему для меня:
Вы можете создать функцию на своем локальном сервере, которая выполняет тот же запрос, что и удаленная функция (если вы знаете реализацию удаленной функции), поскольку вы можете обращаться к таблицам и "статическим вызовам" (по openquery) с помощью нет проблем.
В примере, если удаленная функция выглядит примерно так:
CREATE FUNCTION dbo.[remote_function] (@param1 varchar(200))
RETURNS TABLE AS RETURN
( SELECT col1, col2, col3 FROM [remote_db].[dbo].[remote_table] where col1 = @param1)
GO
Вы можете создать функцию на локальном сервере:
CREATE FUNCTION dbo.[local_function] (@param1 varchar(200))
RETURNS TABLE AS RETURN
( SELECT col1, col2, col3 FROM [remote_server].[remote_db].[dbo].[remote_table] where col1 = @param1)
GO
А затем просто запросите новую функцию, как хотите...
SELECT col1, col2, col3 FROM dbo.local_function(@param1);
GO
Он должен работать без проблем.