génération et accès des données d'une disposition de colonne fixe est facile. Vous pouvez créer des tables temporaires locales en avant et les peupler en appelant des procédures stockées. P>
D'autre part, si vous souhaitez générer des données avec une mise en page de colonne dynamique, vous devez généralement créer une instruction SQL de manière dynamique et l'exécuter avec "EXEC SP_EXECUTSQL". Étant donné que la mise en page de données est inconnue au moment de l'exécution, vous ne pouvez pas créer de TAMP-TABLE-AVANT, et une fois à l'intérieur de l'instruction "EXEC SP_EXECUTSQL", toutes les tables temporaires créées il y a liée à cette portée et disparaître lorsque l'appel retourne, donc Il est beaucoup plus difficile d'accéder aux données (c.-à-d. Vos options sont plus limitées). P>
J'ai une requête qui doit accéder aux données dans une table générée dynamiquement. p>
Le tableau est généré par une procédure stockée, qui construit dynamiquement une requête, la stocke dans une variable "@sql nvarchar (max)" et l'exécute en appelant "exec sp_executeql @statement = @sql". P >
L'instruction @SQL était quelque chose comme "Select * dans #TePTable de ...", mais #Têlable a été détruit à l'époque "EXEC SP_EXECUTEQL" renvoyé. Une solution rapide pour cela était de simplement utiliser "## tentable" (c'est-à-dire une table temporelle temporaire), car elle survit lorsque la procédure stockée revient et je peux facilement y accéder dans la portée de l'appel (car elle a un nom connu / statique ). p>
Je n'aime pas cette solution parce que les tables temporelles temporelles ne sont pas thread-coffre-fort (nom Collistion-wise), et je ne veux pas avoir à gaver avec des noms uniques générés dynamiquement, car je vais juste terminer Avoir à utiliser plus de SQL dynamique pour y accéder ... ce qui me met à la place à la case, laissant les données inaccessibles en dehors du SP. P>
Je ne pense pas que le retour des variables de table (via les paramètres de sortie) est une option (Nouveau sur SQL Server 2008 également), à moins que cela puisse être fait sans avoir à définir un type de table statique. Les tables ma procédure stockées génèrent sont dynamiques et dépendent du ou des paramètres d'entrée passés. P>
Les fonctions de valorisation de la table en ligne ne sont pas une option, car je fais des boucles de code pour construire la requête @SQL et appeler "exec sp_executesql". P>
Fonctions de valorisation de la table multi-instruction (au lieu de la procédure stockée), n'est pas une option, car une telle fonction doit avoir un format de tableau bien défini, alors que je suis en train d'exécuter SQL dyanmic pour renvoyer une table avec une table Nombre variable de colonnes et noms de colonne en fonction des valeurs de paramètre d'entrée. P>
Tout ce que je veux vraiment faire est de sélectionner le jeu de résultats de la requête dynamique dans une nouvelle table, mais je trouve cela difficile, car aucune des œuvres ci-dessus; Particulièrement irritant, c'est la manière dont les tables temporaires locales ne sont pas locales à la session, mais locales à la procédure stockée afin qu'elles disparaissent au retour. La seule Solution que j'ai vu insiste pour que l'utilisation de OpenRowset est le seul moyen, mais je ne veux pas jouer avec des chaînes de connexion à l'intérieur de ma procédure stockée, pour la même raison pour laquelle je ne veux pas inclure le code de gestion unique de noms ... c'est juste plus compliqué qu'il ne devrait être. p>
En résumé, je veux juste exécuter SQL dynamique qui génère un jeu de données d'un format inconnu et pouvoir y accéder facilement à partir de la portée de l'appel. P>
3 Réponses :
Créer la table Temp avant le Changer le SQL pour effectuer un EDIT: P>
Faites de la table assez large pour couvrir toutes les options. P>
Franchement, SQL est conçu pour fonctionner avec des définitions de table fixe: les signatures de sortie variable (tables) mènent au problème que vous avez ... p> sp_executeql code>: il sera toujours dans la portée des champs "intérieurs" comme le
sp_executeql code> p> p>
Insérer code> plutôt que
SELECT..Into ... Code> P>
Cela ne fonctionnera pas, car je ne peux pas créer le tableau temporel vers le haut, car la définition de la table provient de l'instruction SQL générée dystifiée. Si la disposition de la colonne de la table était statique, je pouvais simplement créer la table Temp dans la portée actuelle et je n'aurais pas de problème. Cependant, comme vous pouvez le voir ... Lorsque l'instruction "SELECT" est générée de manière dynamique, et doit être exécutée avec "EXEC SP_EXECUTEQL", alors il y a le problème d'accéder aux données dans la limite de la portée de la procédure stockée.
@Triynko: Voir ma mise à jour s'il vous plaît. Vous avez choisi de faire ce que SQL ne supporte pas bien le tout pour que vos options soient limitées.
Droit. C'est pourquoi je pose ici ici pour trouver ces options. J'ai trouvé une belle rupture des options ici ... Sommarskog.se/share_data.html dans un Article sur «Partage de données entre procédures stockées», mais je suis toujours optimiste / travaillant sur une meilleure solution. L'option OpenRowset est toujours agréable, car elle semble supporter exactement que je souhaite faire (sélectionnez directement dans une requête dans une requête dynamique), mais je déteste les implications de performance et la syntaxe de devoir gérer les connexions à l'intérieur du SP.
Faire le tableau suffisamment large n'est pas une bonne option non plus, car cela signifie vraiment traiter la table comme une sorte de conteneur générique, ce qui rend difficile l'accès des données. En tant que conteneur générique, il aura des noms de colonnes génériques, auquel cas mes requêtes statiques qui s'attendent à ce que les données nommées dans des colonnes nommées, il faudrait alors utiliser des données renvoyées à partir de la procédure stockée à propos des colonnes (ordonnances) contenant les données souhaitées.
Une option clunky mais possible consiste à créer une table à colonne unique dans l'appelant, puis modifiez-la dans la callee. Cela se contente du problème d'étendue, mais rend les choses assez difficiles ...
Si vous construisez une procédure stockée qui accepte les noms de table d'entrée et de sortie, ce qui rend le deuxième tableau exactement comme le premier en laissant tomber et en ajoutant des colonnes, vous pourrait avoir une solution plus générale. p>
Sélection de Notez que le nom de la table dans la vue n'est pas Pour l'utiliser pratiquement, au lieu de remplir la première table avec des données, Puis transformez la deuxième table et copier les données dans celui-ci, je suggérerais de créer une table vide d'abord en exécutant votre processus avec un Comme je l'ai dit, il pourrait être utile dans certains situations étroites où aucune autre option n'est disponible. p> p> templdb.information_schema.columns code> vous permettra de trouver les informations de colonne sur n'importe quelle table Temp (que vous pouvez détecter si le nom de la table commence avec
# code>). Voici un exemple: p>
#blah code> (ce sera probablement quelque chose comme
# #blah ___ {Beaucoup de soulignes} ___ 00000000021D code> Ainsi l'utilisation de
objet_id () code> pour corréler les deux. p>
ajouté haut 0 code> ou
où 1 = 0 code>, puis Copier la structure de la table à la bonne avec votre spectr de copie de table, puis en exécutant le processus de données pour réaliser une seule fois sur la table correcte. P>
Alors, je copie ma réponse de Insérer les résultats de une procédure stockée dans une table temporaire . J'espère que ça aide. Oui, c'est une table temporaire mondiale à nouveau et le seul différent est le gestionnaire annexé là-bas.
J'ai rencontré le même problème et voici ce que j'ai fait pour cela de Neufid () code> Pour éviter que plusieurs utilisateurs exécutent les procédures / scripts de magasin en même temps, la douleur à la table temporaire mondiale. P>
DECLARE @sql varchar(max) = '',
@tmp_global_table varchar(255) = '##global_tmp_' + CONVERT(varchar(36), NEWID())
SET @sql = @sql + 'select * into [' + @tmp_global_table + '] from YOURTABLE'
EXEC(@sql)
EXEC('SELECT * FROM [' + @tmp_global_table + ']')
Pourquoi le bowvote? Bien que l'affiche tente de faire quelque chose de SQL n'est pas vraiment destinée à faire, il a évidemment mis des efforts à considérer les différentes options, et il a clairement exprimé son objectif clairement.
Ce problème m'intéresse, parce que cela semble être quelque chose que SQL devrait vraiment gérer très bien. Le vrai problème ici est de savoir comment la portée des tables temporaires locales est trop limitée. Ce que nous pourrions vraiment utiliser est un troisième type de table temporaire pouvant être créé dans les champs d'enfants, mais est liée à la portée d'appel de niveau supérieur. Les variables de table sont agréables à être transmises et enfin dans SQL Server 2008 qui peuvent être transmises en tant que paramètres de sortie, mais ... ils nécessitent toujours une définition fixe et un type pré-déclaré pour les transmettre en tant que paramètres de sortie.
Je n'aurais pas pu le dire mieux moi-même! J ai exactement le même problème. BTW, je souhaite que T-SQL a pris en charge une «variable de table variante» qui ne nécessite pas de structure prédéterminée.