web-dev-qa-db-ja.com

SELECTとINSERTでOPENQUERYはどう違いますか?

次のクエリがリンクサーバーから結果セットを取得することを知っています。

SELECT * FROM openquery(DEVMYSQL, 
    'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast')

しかし、これは挿入に関しては同じケースですか?結果セットをプルダウンしますか、それとも列情報を取得しますか?

INSERT INTO openquery(DEVMYSQL, 
     'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast')

前者の場合、これは非常に非効率的です。返される結果セットを制限する必要があり、これはINSERTに影響しますか?

これは基本的に、OPENQUERYSELECTに関してINSERTがどのように機能するかに関する質問です。

私はどんな助けにも感謝します。

13
Abs

INSERTで何を達成しようとしているかわかりません。

正しい構文(リモートサーバーに挿入する場合)は次のようになります。

INSERT into openquery(MyServer, 'dbo.event_cast') values ('','')

選択は、追加情報を提供せずに、選択クエリが返すものを取得するまで挿入を遅延させます(利用できません)。また、openqueryを使用すると、挿入にこの構文をより正確に使用できます。

INSERT into myserver.mydatabase.dbo.event_Cast values('','')

ただし、ローカルサーバーに挿入しようとしている場合、selectによって取得される値は次のようになります。

INSERT into dbo.my_localtable SELECT * FROM openquery(DEVMYSQL, 'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast')

そして、はい、文は列情報だけでなく値を挿入します。

テーブルをローカルで複製するだけの場合は、

SELECT top 1 * into new_local_event_cast FROM openquery(DEVMYSQL, 'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast');
TRUNCATE TABLE new_local_event_cast;

十分であろう

10
Zelloss

SELECTがレコードを返す場合、INSERTは影響を受けるレコードの数を除いて結果セットを返しません。これは、SET NOCOUNT ONを使用して抑制できます。ただし、抑制が可視性を指すのか、実際に行数が来るのかはわかりません。

    INSERT INTO OPENQUERY(MYSERVER, 'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [Blah].[dbo].[SQL_Drives]')
    SELECT 'X', 2, 'MyServer'

(1 row(s) affected)

INSERTから返されるレコードに関しては、それを実現する唯一の方法はOUTPUT句を使用することです。クライアントマシンはOUTPUT INSERTED行にアクセスできないため、それらを返すことはできません。以下を実行しようとすると、エラーが表示されます。

INSERT INTO OPENQUERY(MYSERVER, 'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [BLAH].[dbo].[SQL_Drives]')
OUTPUT INSERTED.*
SELECT 'X', 2, 'MyServer'

Msg 405, Level 16, State 1, Line 1
A remote table cannot be used as a DML target in a statement which includes an OUTPUT clause or a nested DML statement.


 -- EDIT RESULTS OF PROFILER ---------------------------      


-- Statements that occured on server called through OPENQUERY
    exec sp_cursoropen @p1 output,N'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [MyServer].[dbo].[SQL_Drives]',@p3 output,@p4 output,@p5 output
    select @p1, @p3, @p4, @p5

    exec sp_cursor 180150009,4,0,N'[MyServer].[dbo].[SQL_Drives]',@Drive_Letter='X',@MBFree=2,@Server='MyServer'


--Statements that occured on client
    INSERT INTO OPENQUERY(MyServer, 'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [MyServer].[dbo].[SQL_Drives]')
    SELECT 'X', 2, 'MyServer'
4
PseudoToad

OPENQUERYを使用してINSERTを実行すると、最初にSELECTが実行され、結果が破棄されます。結果セットの列メタデータを使用して、INSERTコマンドの送信方法を決定します。そのため、SELECTの最後にwhere 1=0を常に追加する必要があります。

SQL ServerからMySQLへの適切な構文は次のとおりです。

insert into openquery(MYSQLDEV, 'select * from insert_test where 1=0') values ('test');

MySQL側で一般クエリログをアクティブにすると、SQL Serverからのこれらのコマンドが表示されます。

SET NAMES utf8
SET character_set_results = NULL
SET SQL_AUTO_IS_NULL = 0
set @@sql_select_limit=1
select * from insert_test where 1=0
select * from insert_test where 1=0
INSERT INTO `database`.`insert_test`(`column`) VALUES ('test')

したがって、選択が2回実行されていることがわかります。 where 1=0がない場合、すべての行がMySQLサーバーによって返されます。

1
patrickmdnet