1

これは一日中私を殺してきました=D。助けてください!

シナリオ1:同じサーバー(A、B)上の2つのDBとAには3つのテーブルがあります。クエリはBから実行されます。

シナリオ2:2つのDBの一方のサーバーがもう一方のサーバーにリンクされています。(BにはリンクAがあります)そしてAには3つのテーブルがあります。クエリはBから実行されます。

シナリオ1(リンクされていないサーバー)の場合:

SET @val = ''
SELECT @val = @val + 'Hello, my name is ' + [name] + '!' + CHAR(10) + CHAR(13)
FROM A.sys.tables

戻り値:こんにちは、私の名前はTable1です!こんにちは、私の名前はTable2です!こんにちは、私の名前はTable3です!

シナリオ2(リンクサーバー)の場合:

SET @val = ''
SELECT @val = @val + 'Hello, my name is ' + [name] + '!' + CHAR(10) + CHAR(13)
FROM LINKED.A.sys.tables

戻り値:こんにちは、私の名前はTable3です!

なぜこれらは違うのですか?リンクサーバーでopenquery()を使用すると、結果はシナリオ1と同じになります。可能であればopenquery()の使用を避けようとしています。ありがとう!

4

1 に答える 1

4

残念ながら、これはSQLServerでの文字列連結の信頼性の低い方法です。最も些細な場合を除いて、私はそれを避けます。このKBには、さらにいくつかの情報があります。実行プランと集計連結クエリの結果は、式の場所によって異なります。

そうは言っても、私はあなたの問題を再現し、私の環境で回避策を提供することができました:

SET @val = ''
SELECT @val = @val + 'Hello, my name is ' + replace([name], '', '') + '!' + CHAR(10) + CHAR(13)
FROM LINKED.A.sys.tables

式に空の置換関数を追加したことに注意してください。出力には何もしませんが、ローカルの「計算スカラー」ステップをクエリプランに追加します。これは、リモートクエリに必要と思われるものを返すだけでなく、名前列からすべてのデータをプルバックしてローカルで処理するようです。

replace空の引数を持つ以外に使用するのに適した関数があるかどうかはわかりません。おそらくダブルreverseか何か。ドキュメントに記載されているように、必要に応じて、必ず最大データ型にキャストしてください。

アップデート

問題を解決するのではなく、単に宣言@varするだけで、replace関数と同じように、ローカル処理のために名前列全体(sysname-またはnvarchar(128)-と入力)が返されます。リンクされたサーバー設定と暗黙のキャストのどの組み合わせがこれを引き起こすのかを知るふりをすることはできません。うまくいけば、この分野の知識が豊富な人がチャイムインできます!varchar(max)nvarchar(max)

于 2012-10-22T21:17:32.023 に答える