web-dev-qa-db-fra.com

En quoi OPENQUERY diffère-t-il pour SELECT et INSERT?

Je suis conscient que la requête suivante déroule l'ensemble de résultats d'un serveur lié:

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

Cependant, s'agit-il du même cas pour l'insertion? Va-t-il dérouler l'ensemble de résultats ou va-t-il simplement obtenir les informations de la colonne?

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

Si le premier, c'est très inefficace. Dois-je limiter le jeu de résultats renvoyé et cela affectera-t-il mon INSERT?

Il s'agit essentiellement d'une question sur le fonctionnement de OPENQUERY en ce qui concerne SELECT et INSERT.

J'apprécie toute aide.

13
Abs

Vous ne savez pas ce que vous essayez d'accomplir avec votre INSERT.

La syntaxe correcte (si vous souhaitez insérer sur le serveur REMOTE) doit être

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

La sélection ne fait que retarder votre insertion pour récupérer ce que la requête de sélection renvoie (en vain) sans vous donner d'informations supplémentaires. En outre, avec openquery, vous pouvez utiliser cette syntaxe, plus correcte, pour l'insertion:

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

Mais, si vous essayez d'insérer dans le serveur LOCAL, les valeurs récupérées par la sélection de la syntaxe doivent être:

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

Et oui, la phrase insérera les valeurs, pas seulement les informations de la colonne.

Si vous souhaitez uniquement répliquer la table localement, un simple

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;

suffira

10
Zelloss

Lorsque SELECT renvoie des enregistrements, INSERT ne renvoie aucun jeu de résultats, à l'exception du nombre d'enregistrements concernés. Cela peut être supprimé en utilisant SET NOCOUNT ON; cependant, je ne suis pas sûr si la suppression ferait référence à la visibilité ou au nombre de lignes à venir.

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

(1 row(s) affected)

En ce qui concerne les enregistrements renvoyés par INSERT, la seule façon d'y parvenir est d'utiliser une clause OUTPUT. La machine cliente n'aura pas accès aux lignes OUTPUT INSERTED donc celles-ci ne peuvent pas être retournées. Si vous essayez d'exécuter ce qui suit, vous recevrez une erreur:

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

Lorsque vous utilisez OPENQUERY pour effectuer un INSERT, il effectue d'abord le SELECT et jette les résultats. Il utilise les métadonnées de colonne du jeu de résultats pour déterminer comment envoyer la commande INSERT. Pour cette raison, vous devez toujours ajouter where 1=0 jusqu'à la fin du SELECT.

De SQL Server à MySQL, la syntaxe appropriée est la suivante:

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

Si vous activez le journal général des requêtes du côté MySQL, vous verrez ces commandes provenant de 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')

Vous pouvez donc voir que la sélection est effectuée deux fois. Sans le where 1=0, toutes les lignes seront retournées par le serveur MySQL.

1
patrickmdnet