65

とという名前の2つのSQLServer(SQL Server 2008を実行)がDATA01ありDATA02ます。を指すDATA02リンクサーバー定義があり、適切なユーザーマッピングが設定されています。これらの2つのテーブルを含むデータベースがあります。LINKDATA01DATA01MyDatabase

CREATE TABLE T_A (
    Id int
)

CREATE TABLE T_B (
    Id int,
    Stuff xml
)

からこのコマンドを実行するとDATA02、期待どおりにデータが返されます。

SELECT Id FROM LINK.MyDatabase.dbo.T_A;

ただし、からこのコマンドを実行するとDATA02、エラーが発生します。

SELECT Id, Stuff FROM LINK.MyDatabase.dbo.T_B;

エラーは

XMLデータ型は分散クエリではサポートされていません。リモートオブジェクト'DATA02.MyDatabase.dbo.T_B'にはxml列があります。

そして奇妙なことに、このコマンド:

SELECT Id FROM LINK.MyDatabase.dbo.T_B;

xml列を使用していなくてもSELECT、同じエラーが発生します。どうしたの?

4

3 に答える 3

105

これはSQLServerの欠陥です。テーブルにxml列が存在するだけで、分散クエリに参加できなくなります(たとえば、リンクされたサーバー接続を介してクエリが実行されます)。これは、この「廃止された」ドキュメントに記載されています。現在のバージョンのドキュメントには、これについての言及はないようです。

以前はMicrosoftConnectに関連するバグレポートがありましたが、Azureフィードバックフォーラムを支持して「廃止」されました。このフィードバック項目は、「製品ドキュメントから直接フィードバックを送信してください」という指示で締めくくられています。これは、製品ドキュメントに実際に記載されている場合は問題ありません。この他のフィードバック項目には、Connectから移行されたコメントが含まれており、ステータスは「計画外」です。

以前存在していたConnectバグレポートの1つは、2つの回避策を提供しました。

  1. リモートサーバー上にXML列なしで[a]ビューを作成し、それをクエリします。

    あなたの例では、これにはMyDatabase 次のようなビューを追加することが含まれます。

    CREATE VIEW V_T_B AS SELECT Id FROM T_B;
    

    次に、リンクを介してこのビューにクエリを実行し、Id データを取得できます。次のようなものに注意してください

    SELECT Id FROM ( SELECT Id FROM T_B ) T_B;
    

    動作しません

  2. フォームでパススルークエリを使用する

    SELECT * from OPENQUERY (... )
    

    この方法には、ソースデータベースに変更を加える必要がないという利点があります。欠点は、ローカルデータとリンクトデータの両方に標準の4部構成の命名を使用できなくなったことです。クエリは次のようになります

     SELECT Id FROM OPENQUERY(DATA02, 'SELECT Id FROM T_B') T_B;
    

    実際にxmlデータ必要な場合は、このメソッド(および非xmlデータ型との間のキャスト)が必要になることに注意してください。

     SELECT Id, CAST(Stuff AS XML) Stuff 
     FROM OPENQUERY(DATA02, 'SELECT Id, CAST(Stuff AS nvarchar(max)) Stuff 
                             FROM T_B') T_B;
    

このバグはSQLServer2005で最初に報告され、SQLServer2017では修正されていないことに注意してください。SQLServer2019をまだ確認できていません。

于 2013-01-21T15:36:26.840 に答える
11

これを試して:

  • xmlをnvarchar(max)にキャストして、ソース側にビューを作成します。

CREATE VIEW vXMLTest AS SELECT cast(Stuff as nvarchar(max))as STUFF FROM T_B

  • xmlにキャストして宛先側で選択できます

SELECT Cast(Stuff as XML)as Stuff FROM OPENQUERY(DATA02、'SELECT Stuff FROM vXMLTest')

このソリューションは、2008R2で機能します。

于 2013-07-25T07:40:15.817 に答える
8

私はこれを行う別の方法を見つけました:

  1. Linked Serveron DATA01DATA02または3番目のサーバー(ローカルの場合もあります)を作成します。
  2. を使用してクエリを実行しますEXEC [linked_server].[sp_executesql]

ビューを作成したり使用したりするよりもこの方法を好むのはなぜOPENQUERYですか?

  1. この方法では、リンクサーバーに対するアクセス許可は必要ありません(ビューを作成する必要はありません)。
  2. sp_executesql構文を使用してパラメーターをクエリに渡すことができます( sp_sqlexecuteの詳細については、こちらを参照してください)。またはOPENQUERYを渡す必要があるため、witchは、すべての値をこの関数に正しく入力する必要があることを意味します。STRINGTEXT_LEX

次に例を示します。

DECLARE @UserID UNIQUEIDENTIFIER = ''

DECLARE @SearchForUserParams NVARCHAR(MAX) = N'@UserID UNIQUEIDENTIFIER';  
DECLARE @SearchForUserQuery NVARCHAR(MAX) = 
N'SELECT
    UserID,
    Username,
    Email,
    CONVERT(NVARCHAR(MAX), UserDataXml) AS UserDataXml
FROM User
WHERE UserID = @UserID'

EXEC [linked_server].[dbo].[sp_executesql] 
    @SearchForUserQuery,
    @SearchForUserParams,
    @UserID = @UserID
于 2018-11-21T20:57:37.937 に答える