Вопрос по sql-server-2008, sp-executesql, openquery, linked-server, permissions – Обходной путь для удаленного вызова табличной функции в SQL Server имеет еще больше проблем

12

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

Эта табличная функция должна вызываться с удаленного сервера. К сожалению, вызов не выполняется на связанном сервере с ошибкой:

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 или нет, и, как я уже сказал, это происходит только при вызове табличной функции.

Есть идеи как решить это?

Ваш Ответ

2   ответа
14

Вы пробовали этот вариант - в основном вы нажимаете, чтобы вызов функции происходил локально на удаленном блоке:

EXEC REMOTE_SERVER_NAME.db_name..sp_executesql N'SELECT * 
  FROM dbo.MyTableValuedFunctionName();';
Ну, в любом случае этот синтаксис кажется проще, чем возиться с OPENQUERY. Даже если кажется, что у вас должна быть локальная копия вашей табличной функции, если половина ее работы заключается в том, чтобы связываться с вызывающим сервером ...
Одна из причин, по которой я связываю серверы, заключается в том, чтобы избегать зеркального отображения данных. Весь смысл их связывания заключается в том, что можно запросить единую универсальную копию данных. Просто очень жаль, что SQL Server 2008 не поддерживает простой запрос к удаленной табличной функции. Надеюсь, SQL Server 2012 будет. Triynko
Причина, по которой запрос ссылается обратно, заключается в том, что удаленный запрос должен выполнить несколько левых соединений со списком имен пользователей на главном сервере. Нет никакого способа передать этот список на удаленный сервер, кроме как для того, чтобы удаленный сервер запросил его как связанный сервер. Любая другая форма запроса будет сложной или ненадежной, включая внешние объединения и объединенные значения полей имени пользователя. Triynko
Мне приходилось сталкиваться с этой ситуацией в прошлой жизни. Я считаю, что лучше копировать метаданные пользователя на вызывающий сервер. Это может быть осуществимо и работать достаточно хорошо, в зависимости от того, какую технологию вы выбираете для репликации данных и как часто они меняются.
OPENQUERY уже заставляет функцию запускаться локально на удаленном сервере, и это не имело значения, что sp_executesql выполнялся на локальном сервере, потому что возникала проблема, выполнял ли я OPENQUERY с sp_executesql или без него. Это на самом деле работает сейчас хорошо; проблема заключалась в том, что табличная функция была связана с исходным сервером, и я забыл добавить сопоставление удаленного пользователя обратно на связанный сервер, а не просто свое имя пользователя, которое я использовал бы, если бы выполнял запрос локально на удаленном сервере. против связанного локального сервера. Triynko
-1

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

Вы можете создать функцию на своем локальном сервере, которая будет выполнять тот же запрос, что и удаленная функция (при условии, что вы знаете реализацию удаленной функции), поскольку вы можете обращаться к таблицам и & quot; static-call-functions & quot; (по 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

Это должно работать без проблем.

Похожие вопросы