13

さまざまなパラメーターを使用して複数回実行する必要がある一連のパラメーターを含むクエリがあったため、それをテーブル値関数でラップしました。

そのテーブル値関数は、リモート サーバーから呼び出される必要がありました。残念ながら、リンク サーバーでの呼び出しは次のエラーで失敗します。

Msg 4122, Level 16, State 1, Line 29
Remote table-valued function calls are not allowed.

Microsoft は、"テーブル値関数をリモートで呼び出す" 機能が SQL Server 2008 から除外されていたことを認めています。 - 通話は許可されていません

OPENQUERY 構文を使用する回避策を発見しました。これにより、クエリをリモート サーバー上でローカルに実行し、結果セットを返すことができます。参照: http://social.msdn.microsoft.com/Forums/en/transactsql/thread/7a6e4aa1-630b-4ad5-aee5-15139987adbd

残念ながら、この回避策には回避策が必要でした。これは、引数として文字列が必要なためです。つまり、OPENQUERY 構文を使用して変数を渡すことはできず、変数を含めたい場合のように、その中に文字列を連結することさえできません。リモート テーブル値関数に渡したい。回避策の回避策は、動的 SQL を使用して OPENQUERY クエリを明示的に構築し、通常の文字列が確実に渡されるようにすることです。参照: 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.

ユーザー名のマッピングが存在するため、このエラーが発生する理由がわかりません。テーブル値関数を実際のテーブルに置き換えるだけで、結果が正常に返されます。この問題は、sp_executesql で実行されるかどうかに関係なく、OPENQUERY ステートメントで発生します。前述のとおり、テーブル値関数を呼び出す場合にのみ発生します。

これを解決する方法はありますか?

4

2 に答える 2

16

このバリエーションを試しましたか - 基本的に、リモートボックスでローカルに発生するように関数への呼び出しをプッシュします:

EXEC REMOTE_SERVER_NAME.db_name..sp_executesql N'SELECT * 
  FROM dbo.MyTableValuedFunctionName();';
于 2012-06-11T14:51:29.947 に答える
0

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

問題なく動作するはずです。

于 2015-06-06T21:30:06.290 に答える