DATA01
とDATA02
という名前の2つのSQL Server(SQL Server 2008を実行)があります。 DATA02
には、適切なユーザーマッピングが設定されたDATA01
を指すリンクサーバー定義LINK
があります。 DATA01
には、これらの2つのテーブルを含むデータベースMyDatabase
があります。
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
ingしていないのに!何が起きているのですか?
これは、SQL Server内の欠陥です。テーブル上のxml列の単なるexistenceにより、分散クエリに参加できなくなります(リンクサーバー接続を介したクエリなど)。これは ドキュメントで言及されています ですが、特に顕著ではありません。 メインの接続バグレポートはこちら 、および 同様のレポートはこちら をご覧ください。後者には2つの回避策があります。
リモートサーバー上に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;
動作しません。
フォームでパススルークエリを使用する
SELECT * from OPENQUERY (... )
この方法には、ソースデータベースを変更する必要がないという利点があります。欠点は、ローカルデータとリンクデータの両方に標準の4部構成の命名規則を使用できなくなったことです。クエリは次のようになります
SELECT Id FROM OPENQUERY(DATA02, 'SELECT Id FROM T_B') T_B;
実際にdoがxmlデータを必要とする場合、このメソッドは(非xmlデータ型との間のキャストとともに)required:
SELECT Id, CAST(Stuff AS XML) Stuff
FROM OPENQUERY(DATA02, 'SELECT Id, CAST(Stuff AS nvarchar(max)) Stuff
FROM T_B') T_B;
このバグはSQL Server 2005で最初に報告され、SQL Server 2014では修正されていないことに注意してください。
これを試して:
CREATE VIEW vXMLTest AS SELECT cast(stuff as nvarchar(max))as STUFF FROM T_B
SELECT Cast(Stuff as XML)as Stuff FROM OPENQUERY(DATA02、 'SELECT Stuff FROM vXMLTest')
このソリューションは2008R2で機能します。
私はこれを行う別の方法を見つけました:
Linked Server
、DATA01
、または3番目のサーバー(ローカルの場合もある)にDATA02
を作成します。EXEC [linked_server].[sp_sqlexecute]
を使用してクエリを実行します。ビューの作成やOPENQUERY
の使用よりもこの方法を好むのはなぜですか?
sp_sqlexecute
構文を使用してクエリにパラメーターを渡すことができます( sp_sqlexecuteの詳細はこちら )。 OPENQUERY
の場合、STRING
またはTEXT_Lex
を渡す必要があります。witchは、すべての値をこの関数に直接入力する必要があることを意味します。以下に例を示します。
DECLARE @UserID UNIQUEIDENTIFIER = ''
DECLARE @SearchForUserParams NVARCHAR(MAX) = N'@UserID UNIQUEIDENTIFIER';
DECLARE @SearchForUserQuery NVARCHAR(MAX) =
N'SELECT
UserID,
Username,
Email,
CONCART(NVARCHAR(MAX), UserDataXml) AS UserDataXml
FROM User
WHERE UserID = @UserID
'
EXEC [linked_server].[dbo].[sp_executesql]
@SearchForUserQuery,
@SearchForUserParams,
@UserID = @UserID