J'ai trois procédures stockées Sp1
, Sp2
et Sp3
.
Le premier ( Sp1
) exécutera le second ( Sp2
) et enregistrera les données renvoyées dans @tempTB1
et le second exécutera le troisième ( Sp3
) et enregistrera les données dans @tempTB2
.
Si j'exécute le, Sp2
cela fonctionnera et il me renverra toutes mes données du Sp3
, mais le problème est dans le Sp1
, lorsque je l'exécute, il affichera cette erreur:
L'instruction INSERT EXEC ne peut pas être imbriquée
J'ai essayé de changer l'emplacement de execute Sp2
et cela m'affiche une autre erreur:
Impossible d'utiliser l'instruction ROLLBACK dans une instruction INSERT-EXEC.
sp_help_jobactivity
).C'est le seul moyen «simple» de le faire dans SQL Server sans une fonction créée géante alambiquée ou un appel de chaîne SQL exécuté, qui sont tous deux des solutions terribles:
EXEMPLE:
Remarque : Vous DEVEZ utiliser 'set fmtonly off', ET vous NE POUVEZ PAS ajouter de SQL dynamique à cela soit à l'intérieur de l'appel openrowset, soit pour la chaîne contenant vos paramètres de procédure stockée, soit 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 elle surpasse la table temporaire dans la plupart des cas.
la source
OK, encouragé par jimhark, voici un exemple de l'ancienne approche de table de hachage unique: -
la source
Mon travail autour de ce problème a toujours été d'utiliser le principe que les tables temporaires de hachage unique sont dans la portée de tout processus appelé. Donc, j'ai un commutateur d'option dans les paramètres de proc (par défaut réglé sur off). Si cette option est activée, le proc appelé insérera les résultats dans la table temporaire créée dans le proc appelant. Je pense que dans le passé, j'ai poussé un peu plus loin et mis du code dans le proc appelé pour vérifier si la table de hachage unique existe dans la portée, si elle le fait, insérez le code, sinon retournez le jeu de résultats. Semble bien fonctionner - meilleure façon de passer de grands ensembles de données entre les processus.
la source
Cette astuce fonctionne pour moi.
Vous n'avez pas ce problème sur le serveur distant, car sur le serveur distant, la dernière commande d'insertion attend le résultat de la commande précédente à exécuter. Ce n'est pas le cas sur le même serveur.
Profitez de cette situation pour une solution de contournement.
Si vous disposez des autorisations nécessaires pour créer un serveur lié, faites-le. Créez le même serveur que le serveur lié.
maintenant votre commande Sql dans le SP1 est
Croyez-moi, cela fonctionne même si vous avez un insert dynamique dans SP2
la source
J'ai trouvé qu'une solution consiste à convertir l'un des prods en une fonction de table. Je me rends compte que ce n'est pas toujours possible et introduit ses propres limites. Cependant, j'ai toujours pu trouver au moins une des procédures un bon candidat pour cela. J'aime cette solution, car elle n'introduit aucun "hacks" dans la solution.
la source
J'ai rencontré ce problème en essayant d'importer les résultats d'un processus stocké dans une table temporaire, et ce processus stocké a été inséré dans une table temporaire dans le cadre de sa propre opération. Le problème est que SQL Server n'autorise pas le même processus à écrire dans deux tables temporaires différentes en même temps.
La réponse OPENROWSET acceptée fonctionne bien, mais je devais éviter d'utiliser un SQL dynamique ou un fournisseur OLE externe dans mon processus, j'ai donc emprunté une voie différente.
Une solution de contournement simple que j'ai trouvée était de changer la table temporaire de ma procédure stockée en variable de table. Cela fonctionne exactement de la même manière qu'avec une table temporaire, mais n'est plus en conflit avec mon autre insert de table temporaire.
Juste pour éviter le commentaire, je sais que quelques-uns d'entre vous sont sur le point d'écrire, me mettant en garde contre les variables de table en tant que tueurs de performances ... Tout ce que je peux vous dire, c'est qu'en 2020, cela rapporte des dividendes de ne pas avoir peur des variables de table. Si c'était en 2008 et que ma base de données était hébergée sur un serveur avec 16 Go de RAM et fonctionnant sur des disques durs à 5400 tr / min, je pourrais être d'accord avec vous. Mais c'est 2020 et j'ai une baie SSD comme stockage principal et des centaines de Go de RAM. Je pourrais charger la base de données de toute ma société dans une variable de table et avoir encore beaucoup de RAM à revendre.
Les variables de table sont de retour au menu!
la source
J'ai eu le même problème et le même souci concernant le code en double dans deux sprocs ou plus. J'ai fini par ajouter un attribut supplémentaire pour "mode". Cela a permis au code commun d'exister dans un sproc et le flux dirigé par mode et l'ensemble de résultats du sproc.
la source
qu'en est-il simplement de stocker la sortie dans la table statique? Comme
ce n'est pas idéal, mais c'est si simple et vous n'avez pas besoin de tout réécrire.
MISE À JOUR : la solution précédente ne fonctionne pas bien avec les requêtes parallèles (accès asynchrone et multi-utilisateur) donc maintenant je suis en utilisant des tables temporaires
spGetData
contenu de procédure stockée imbriquéela source
Déclarez une variable de curseur de sortie sur le sp interne:
Déclarez ensuite un curseur c sur la sélection que vous souhaitez retourner. Puis ouvrez le curseur. Puis définissez la référence:
NE PAS fermer ou réallouer.
Maintenant, appelez le sp interne à partir de l'extérieur en fournissant un paramètre de curseur comme:
Une fois que le sp interne s'exécute, vous
@cOUT
êtes prêt à aller chercher. Bouclez puis fermez et désallouez.la source
Si vous êtes capable d'utiliser d'autres technologies associées telles que C #, je suggère d'utiliser la commande SQL intégrée avec le paramètre Transaction.
J'ai créé une application console simple qui démontre cette capacité qui peut être trouvée ici: https://github.com/hecked12/SQL-Transaction-Using-C-Sharp
En bref, C # vous permet de surmonter cette limitation où vous pouvez inspecter la sortie de chaque procédure stockée et utiliser cette sortie comme vous le souhaitez, par exemple, vous pouvez la transmettre à une autre procédure stockée. Si la sortie est correcte, vous pouvez valider la transaction, sinon vous pouvez annuler les modifications à l'aide de la restauration.
la source
Sur SQL Server 2008 R2, j'avais une incompatibilité dans les colonnes de table qui a provoqué l'erreur de restauration. Il a disparu lorsque j'ai corrigé ma variable de table sqlcmd remplie par l'instruction insert-exec pour qu'elle corresponde à celle renvoyée par le proc stocké. Il manquait org_code. Dans un fichier cmd Windows, il charge le résultat de la procédure stockée et le sélectionne.
la source