web-dev-qa-db-fra.com

L'utilisation de INSERT INTO ... EXEC AT le serveur lié dans la table temporaire échoue avec Msg 7391

J'utilise SQL Server 2014. Je veux exécuter EXEC (@remotecmd) AT [server_name]; (@remotecmd est un SQL dynamique et non une procédure stockée) dans ##eapb. Mon code est

insert into ##eapb
EXEC (@remotecmd) AT [ADSQLDB3S\DEV];

Mais je reçois l'erreur:

Le fournisseur OLE DB "SQLNCLI11" pour le serveur lié "nom_serveur" a renvoyé le message "Le gestionnaire de transactions a désactivé sa prise en charge des transactions distantes/réseau.".
Msg 7391, niveau 16, état 2, ligne 71
L'opération n'a pas pu être effectuée car OLE fournisseur de base de données "SQLNCLI11" pour le serveur lié "nom_serveur" n'a pas pu démarrer une transaction distribuée.

Si je supprime le insert into ##eapb, Je n'ai aucune erreur.

Le serveur lié a l'option RPC Out définie sur True.

5
Edgar Allan Bayron

Dans mes tests (sur une autre instance sur le même serveur, pas sur un serveur distinct), cela fonctionnait si j'avais l'option Serveur lié de Activer la promotion des transactions distribuées pour RPC définie sur "Faux". Vous pouvez accomplir cela via la commande suivante:

EXEC master.dbo.sp_serveroption
       @server = N'{linked_server_name}',
       @optname = N'remote proc transaction promotion',
       @optvalue = N'false';

Cela a fonctionné avec le coordinateur de transactions distribuées (MSDTC) à la fois sur ON (en cours d'exécution) et sur OFF (arrêté).

Si vous avez normalement besoin de l'option "promotion de transaction de proc à distance" définie sur "Vrai", et si la définir sur "Faux" permet à INSERT...EXEC De fonctionner, vous pouvez configurer un autre serveur lié avec tout de même propriétés sauf cette option étant différente.

Le principal inconvénient de la désactivation de la "promotion de proc à distance" est que ce n'est pas une transaction sur le serveur distant . Donc, si une erreur s'y produit, vous n'obtiendrez pas les données insérées localement (évidemment), mais s'il y avait des instructions DML exécutées à distance, celles-ci pourraient toujours être validées (selon qu'il s'agissait d'une seule instruction ou de plusieurs instructions). Néanmoins, vous pouvez/devez toujours utiliser la gestion des transactions appropriée sur la requête distante (c'est-à-dire utiliser la construction TRY...CATCH):

CREATE TABLE #Local ([name] [sysname]);


INSERT INTO #Local ([name])
    EXEC (N'
BEGIN TRY
    BEGIN TRAN;
    SELECT [name] FROM sys.servers WHERE 1/0 = ''a'';
    COMMIT;
END TRY
BEGIN CATCH
    ROLLBACK TRAN;
    THROW;
END CATCH;
') AT [{linked_server_name}];

P.S. L'option RPC Out Doit être activée/True. Cela n'a pas été mentionné ci-dessus car selon un commentaire sur la question, cette option est déjà correctement paramétrée.

5
Solomon Rutzky

Je peux utiliser:

SELECT *
INTO #TABLATEMP
FROM Openquery([link-server-name],N' Execute anything ')

Select Campo1, Campo2, Campo3, .... CampoN
FRom #TABLATEMP

DROP TABLE #TABLATEMP

-- C'est tout!!!

1
Erwin Gonzalez