126 votes

Erreurs : "L'instruction INSERT-EXEC ne peut pas être imbriquée" et "Impossible d'utiliser l'instruction ROLLBACK dans une instruction INSERT-EXEC". Comment résoudre ce problème ?

J'ai trois procédures stockées Sp1 , Sp2 y Sp3 .

Le premier ( Sp1 ) exécutera le second ( Sp2 ) et sauvegarder les données retournées dans @tempTB1 et le deuxième exécutera le troisième ( Sp3 ) et sauvegarder les données dans @tempTB2 .

Si j'exécute le Sp2 cela fonctionnera et me renverra toutes mes données depuis le Sp3 mais le problème se situe au niveau de la Sp1 Lorsque je l'exécute, il affiche cette erreur :

L'instruction INSERT EXEC ne peut pas être imbriquée

J'ai essayé de changer la place de execute Sp2 et il m'affiche une autre erreur :

Impossible d'utiliser l'instruction ROLLBACK dans une instruction INSERT-EXEC.

125voto

eddiegroves Points 4991

Il s'agit d'un problème courant lorsque l'on tente de faire remonter des données à partir d'une chaîne de procédures stockées. Une restriction de SQL Server est que vous ne pouvez avoir qu'un seul INSERT-EXEC actif à la fois. Je vous recommande de consulter Comment partager des données entre procédures stockées qui est un article très complet sur les modèles permettant de contourner ce type de problème.

Par exemple, une solution pourrait consister à transformer Sp3 en une fonction à valeur de tableau.

1 votes

Lien brisé OU site non réactif.

11 votes

Avez-vous une idée de la raison technique pour laquelle vous ne l'autorisez pas ? Je ne trouve aucune information à ce sujet.

2 votes

Malheureusement, ce n'est souvent pas une option. De nombreux types d'informations importantes ne sont de manière fiable disponible dans le système procédures stockées (parce que, dans certains cas, la vue de gestion respective contient des données non fiables/obsolètes ; un exemple est l'information renvoyée par la fonction sp_help_jobactivity ).

25voto

Mitch Stokely Points 51

C'est la seule façon "simple" de le faire dans SQL Server sans une fonction créée géante et alambiquée ou un appel de chaîne sql exécuté, qui sont tous deux des solutions terribles :

  1. créer une table temporaire
  2. d'y insérer les données de votre procédure stockée

EXEMPLE :

INSERT INTO #YOUR_TEMP_TABLE
SELECT * FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off EXEC [ServerName].dbo.[StoredProcedureName] 1,2,3')

Note : Vous DEVEZ utiliser 'set fmtonly off', ET vous NE POUVEZ PAS ajouter de sql dynamique dans l'appel openrowset, que ce soit pour la chaîne contenant les paramètres de votre procédure stockée ou pour le nom de la table. C'est pourquoi vous devez utiliser une table temporaire plutôt que des variables de table, ce qui aurait été mieux, car cela surpasse la table temporaire dans la plupart des cas.

0 votes

Il n'est pas nécessaire d'utiliser SET FMTONLY OFF. Vous pouvez simplement ajouter un IF(1=0) qui renvoie une table vide avec les mêmes types de données que la procédure renvoie normalement.

3 votes

Les variables de table sont censées être utilisées pour les petits ensembles de résultats, car l'optimiseur de requêtes ne tient pas de statistiques sur les variables de table. Les variables de table sont censées être utilisées pour les petits ensembles de résultats, car l'optimiseur de requêtes ne tient pas de statistiques sur les variables de table. Voici un bel article de blog à ce sujet mssqltips.com/sqlservertip/2825/

0 votes

@gh9 oui, mais c'est une idée horrible pour les grands ensembles de résultats de toute façon. Les statistiques et l'utilisation d'une table réelle dans la base de données temporaire peuvent entraîner une surcharge importante. J'ai une procédure qui renvoie un jeu d'enregistrements avec 1 ligne de valeurs actuelles (interrogation de plusieurs tables) et une procédure qui stocke cela dans une variable de table et le compare aux valeurs d'une autre table avec le même format. Le passage d'une table temporaire à une variable de table a fait passer le temps moyen de 8 ms à 2 ms, ce qui est important lorsque la procédure est appelée plusieurs fois par seconde tout au long de la journée et 100 000 fois dans un processus nocturne.

6voto

Roman K Points 56

J'ai trouvé un moyen de contourner le problème en convertissant l'une des prods en une fonction à valeur de tableau. Je me rends compte que ce n'est pas toujours possible et que cela introduit ses propres limites. Cependant, j'ai toujours pu trouver au moins une des procédures comme étant un bon candidat pour cela. J'aime cette solution, parce qu'elle n'introduit pas de "hack" dans la solution.

0 votes

Mais l'inconvénient est un problème de gestion des exceptions si la fonction est complexe, n'est-ce pas ?

2voto

NG. Points 1564

Je doute que vous puissiez réaliser l'exécution de l'insertion imbriquée.
Références : http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/e66c9e71-4424-4cf3-920c-6725ffc40162/ Mais je pense que cela pourrait vous aider http://www.sqlservercentral.com/Forums/Topic13595-8-1.aspx#bm68301

1voto

phoenixAZ Points 111

J'ai eu le même problème et la même inquiétude concernant le code dupliqué dans deux ou plusieurs sprocs. J'ai fini par ajouter un attribut supplémentaire pour "mode". Cela permettait au code commun d'exister à l'intérieur d'un sproc et le mode dirigeait le flux et l'ensemble des résultats du sproc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X