none
ストアド内でリンクサーバーの名前を動的に変えてSELECT INTOを実行したい RRS feed

  • 質問

  • こんにちは。お世話になります。

    【環境】
    ・SQL Server2008 R2

    【やりたいこと】
    1.サーバー側のSQL Server2008 R2に、ローカル側にあるSQL Server 2008 R2へのリンクサーバを作成します
    2.ストアドの引数に1で作成したリンクサーバー名を渡します。
    3.2の引数を用いて、SELECT INTOを実行したいと考えています。

    【現状】
    DECLARE @sql   VARCHAR(8000)
    DECLARE @変数  VARCHAR(8000)
    SET @変数 = '[リンクサーバー名]'

    SET @sql = 'SELECT * INTO [データベースB].[dbo].[テーブルB]'
    SET @sql = @sql + 'FROM [データベースA].[dbo].[テーブルA]'
    EXECUTE (@sql) AT [リンクサーバー名]
    ≪結果≫
    ローカル側にテーブルBが作成される


    SET @sql = 'SELECT * INTO [データベースB].[dbo].[テーブルB]'
    SET @sql = @sql + 'FROM [データベースA].[dbo].[テーブルA]'
    EXECUTE (@sql) AT @変数
    ≪エラー内容≫
    メッセージ 102、レベル 15、状態 1、行 9
    '@変数' 付近に不適切な構文があります。


    SET @sql = 'SELECT * INTO ' + @変数 +'.[データベースB].[dbo].[テーブルB]'
    SET @sql = @sql + 'FROM [データベースA].[dbo].[テーブルA]'
    EXECUTE (@sql)
    ≪エラー内容≫
    メッセージ 117、レベル 15、状態 1、行 1
    オブジェクト の名前 'リンクサーバー名.データベース名.dbo.テーブル名' は、プレフィックスの最大数を超えています。最大数は 2 です。

    【質問】
    ストアド内でリンクサーバーの名前を動的に変えて、SELECT INTOを行う方法を教えてください。
    また、リンクサーバー以外の方法があれば教えてください。
    よろしくお願いします。


    • 編集済み nyandaba 2011年11月24日 7:14
    2011年11月24日 7:12

回答

  • 適当に書いたコードなので…整理すると

    SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];
    

    EXECUTE (N'SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];') AT [リンクサーバー名];
    

    EXECUTE (N'EXECUTE (N''SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];'') AT [リンクサーバー名];');
    

    ですよね。このEXECUTEに渡す文字列(丸かっこの中)を作ればいいので

    DECLARE @sql NVARCHAR(4000) = N'EXECUTE (N''SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];'') AT ' + @変数 + N';'
    EXECUTE (@sql);
    

    でだめですか?

    • 回答としてマーク nyandaba 2011年11月25日 4:53
    2011年11月25日 1:09

すべての返信

  • 私も以前に変数に関する質問をしていますが、EXECUTE文の「AT linked_server_name」に変数は使えません。EXECUTE文を組み立てるためにもう1段EXECUTE文が必要なようです。

    DECLARE @execute VARCHAR(8000);
    SET @execute = N'EXECUTE @sql AT ' + @変数 + N';';
    EXECUTE @execute;

    # みたいな…

    2011年11月24日 7:52
  • 佐祐理さん、こんにちは。
    回答をしていただき、ありがとうございます。

    教えていただいた内容を確認し、試してみたところ、以下のようなエラーが出ました。

    DECLARE @sql   VARCHAR(8000)
    DECLARE @変数  VARCHAR(8000)
    SET @変数 = '[リンクサーバー名]'
    
    SET @sql = 'SELECT * INTO [データベースB].[dbo].[テーブルB]'
    SET @sql = @sql + ' FROM [データベースA].[dbo].[テーブルA]'
    
    DECLARE @execute VARCHAR(8000);
    SET @execute = N'EXECUTE (@sql) AT ' + @変数 + N';';
    EXECUTE @execute;

    ≪エラー内容≫
    メッセージ 203、レベル 16、状態 2、行 16
    名前 'EXECUTE (@sql) AT [リンクサーバー名];' は有効な識別子ではありません。

    @sqlを外に出して実行しても、同様のエラーが出ます。

    SET @execute = N'EXECUTE (' + @sql + ') AT ' + @変数 + N';';

    ≪エラー内容≫
    メッセージ 203、レベル 16、状態 2、行 16
    名前 'EXECUTE (SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA]) AT [リンクサーバー名];' は有効な識別子ではありません。

    『EXECUTE (@sql) AT [リンクサーバー名]』で実行すると、ローカル側にテーブルBが作成されます。

    どのように対処すればよろしいでしょうか。
    教えてください。よろしくお願い致します。


    • 編集済み nyandaba 2011年11月25日 4:54
    2011年11月25日 0:41
  • 適当に書いたコードなので…整理すると

    SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];
    

    EXECUTE (N'SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];') AT [リンクサーバー名];
    

    EXECUTE (N'EXECUTE (N''SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];'') AT [リンクサーバー名];');
    

    ですよね。このEXECUTEに渡す文字列(丸かっこの中)を作ればいいので

    DECLARE @sql NVARCHAR(4000) = N'EXECUTE (N''SELECT * INTO [データベースB].[dbo].[テーブルB] FROM [データベースA].[dbo].[テーブルA];'') AT ' + @変数 + N';'
    EXECUTE (@sql);
    

    でだめですか?

    • 回答としてマーク nyandaba 2011年11月25日 4:53
    2011年11月25日 1:09
  • 佐祐理さん、こんにちは。
    回答をしていただき、ありがとうございます。

    先程のエラーの原因は、
    EXECUTEに渡す文字列のSQLの部分をシングルコーテーションで括らなかったのが原因だったのですね。
    教えていただいた内容で再度試してみたところ、エラー無く実行することができました。

    DECLARE @sql   VARCHAR(8000)
    DECLARE @変数  VARCHAR(8000)
    
    SET @変数 = '[リンクサーバー名]'
    
    SET @sql = N'EXECUTE (' + N''''
    SET @sql = @sql + N'SELECT * INTO [データベースB].[dbo].[テーブルB]'
    SET @sql = @sql + N' FROM [データベースA].[dbo].[テーブルA];'
    SET @sql = @sql + N'''' + N') AT ' + @変数 + N';'
    
    EXECUTE (@sql);
    


    わかりやすく教えていただき、ありがとうございました。


    • 編集済み nyandaba 2011年11月25日 5:43
    2011年11月25日 4:52