Comment faire un SELECT * INTO [temp table] FROM [stored procedure]
? Pas FROM [Table]
et sans définir [temp table]
?
Select
toutes les données de BusinessLine
dans tmpBusLine
fonctionne bien.
select *
into tmpBusLine
from BusinessLine
J'essaye la même chose, mais en utilisant un stored procedure
qui renvoie des données, ce n'est pas tout à fait la même chose.
select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'
Message de sortie:
Msg 156, niveau 15, état 1, ligne 2 Syntaxe incorrecte près du mot clé 'exec'.
J'ai lu plusieurs exemples de création d'une table temporaire avec la même structure que la procédure stockée de sortie, ce qui fonctionne bien, mais ce serait bien de ne fournir aucune colonne.
Réponses:
Vous pouvez utiliser OPENROWSET pour cela. Regarde. J'ai également inclus le code sp_configure pour activer les requêtes distribuées ad hoc, au cas où il ne serait pas déjà activé.
la source
Si vous souhaitez le faire sans d'abord déclarer la table temporaire, vous pouvez essayer de créer une fonction définie par l'utilisateur plutôt qu'une procédure stockée et faire en sorte que cette fonction définie par l'utilisateur renvoie une table. Alternativement, si vous souhaitez utiliser la procédure stockée, essayez quelque chose comme ceci:
la source
Dans SQL Server 2005, vous pouvez utiliser
INSERT INTO ... EXEC
pour insérer le résultat d'une procédure stockée dans une table. À partir de laINSERT
documentation de MSDN (pour SQL Server 2000, en fait):la source
Ceci est une réponse à une version légèrement modifiée de votre question. Si vous pouvez abandonner l'utilisation d'une procédure stockée pour une fonction définie par l'utilisateur, vous pouvez utiliser une fonction définie par l'utilisateur de table en ligne. Il s'agit essentiellement d'une procédure stockée (qui prendra des paramètres) qui renvoie une table en tant qu'ensemble de résultats; et donc se placera bien avec une instruction INTO.
Voici un bon article rapide à ce sujet et d'autres fonctions définies par l'utilisateur. Si vous avez toujours besoin de conduire pour une procédure stockée, vous pouvez envelopper la fonction définie par l'utilisateur de table en ligne avec une procédure stockée. La procédure stockée transmet simplement les paramètres lorsqu'elle appelle select * à partir de la fonction définie par l'utilisateur de la table en ligne.
Ainsi, par exemple, vous auriez une fonction définie par l'utilisateur de table en ligne pour obtenir une liste de clients pour une région particulière:
Vous pouvez ensuite appeler cette fonction pour obtenir un résultat tel que:
Ou pour faire un SELECT INTO:
Si vous avez toujours besoin d'une procédure stockée, enveloppez la fonction comme telle:
Je pense que c'est la méthode la plus «sans hack» pour obtenir les résultats souhaités. Il utilise les fonctionnalités existantes car elles étaient destinées à être utilisées sans complications supplémentaires. En imbriquant la fonction définie par l'utilisateur de table en ligne dans la procédure stockée, vous avez accès à la fonctionnalité de deux manières. Plus! Vous n'avez qu'un seul point de maintenance pour le code SQL réel.
L'utilisation de OPENROWSET a été suggérée, mais ce n'est pas pour cela que la fonction OPENROWSET était destinée à être utilisée (à partir de Books Online):
L'utilisation de OPENROWSET fera le travail, mais cela entraînera des frais supplémentaires pour l'ouverture des connexions locales et le rassemblement des données. Il peut également ne pas être une option dans tous les cas car il nécessite une autorisation de requête ad hoc qui pose un risque pour la sécurité et peut donc ne pas être souhaitée. En outre, l'approche OPENROWSET empêchera l'utilisation de procédures stockées renvoyant plus d'un jeu de résultats. L'encapsulation de plusieurs fonctions définies par l'utilisateur de valeur de table en ligne dans une seule procédure stockée peut y parvenir.
la source
la source
Si vous ne connaissez pas le schéma, vous pouvez procéder comme suit. Veuillez noter que cette méthode comporte de graves risques pour la sécurité.
la source
Lorsque la procédure stockée renvoie un grand nombre de colonnes et que vous ne souhaitez pas "créer" manuellement une table temporaire pour contenir le résultat, j'ai trouvé que le moyen le plus simple consiste à accéder à la procédure stockée et à ajouter une clause "into" sur le dernière instruction select et ajoutez 1 = 0 à la clause where.
Exécutez la procédure stockée une fois et revenez en arrière et supprimez le code SQL que vous venez d'ajouter. Maintenant, vous aurez une table vide correspondant au résultat de la procédure stockée. Vous pouvez soit "table de script en tant que créer" pour une table temporaire ou simplement insérer directement dans cette table.
la source
SELECT INTO
table temporaire et table de script à partir de la table temporaire? Les tables temporaires apparaissent danstempdb
mais je ne suis pas en mesure de faire un clic droit et de créer un script. Toute aide est appréciée.select ... into new_table
créer implicitement une table réelle.declare @s varchar(max)='';select @s=@s+','+COLUMN_NAME+' '+DATA_TYPE+isnull('('+case CHARACTER_MAXIMUM_LENGTH when -1 then 'max' else cast(CHARACTER_MAXIMUM_LENGTH as varchar(10))end+')','')from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='...';select @s
la source
Votre procédure stockée récupère-t-elle uniquement les données ou les modifie-t-elle également? Si elle est utilisée uniquement pour la récupération, vous pouvez convertir la procédure stockée en fonction et utiliser les expressions de table communes (CTE) sans avoir à la déclarer, comme suit:
Cependant, tout ce qui doit être récupéré du CTE doit être utilisé dans une seule instruction. Vous ne pouvez pas faire
with temp as ...
et essayer de l'utiliser après quelques lignes de SQL. Vous pouvez avoir plusieurs CTE dans une seule instruction pour des requêtes plus complexes.Par exemple,
la source
Si la table de résultats de votre proc stocké est trop compliquée pour taper manuellement l'instruction "create table" et que vous ne pouvez pas utiliser OPENQUERY OU OPENROWSET, vous pouvez utiliser sp_help pour générer la liste des colonnes et des types de données pour vous. Une fois que vous avez la liste des colonnes, il suffit de la formater selon vos besoins.
Étape 1: Ajoutez "dans #temp" à la requête de sortie (par exemple "sélectionnez [...] dans #temp dans [...]").
Le moyen le plus simple consiste à modifier directement la requête de sortie dans le proc. si vous ne pouvez pas modifier le proc stocké, vous pouvez copier le contenu dans une nouvelle fenêtre de requête et y modifier la requête.
Étape 2: exécutez sp_help sur la table temporaire. (par exemple, "exec tempdb..sp_help #temp")
Après avoir créé la table temporaire, exécutez sp_help sur la table temporaire pour obtenir une liste des colonnes et des types de données, y compris la taille des champs varchar.
Étape 3: copiez les colonnes et types de données dans une instruction create table
J'ai une feuille Excel que j'utilise pour formater la sortie de sp_help dans une instruction "create table". Vous n'avez besoin de rien d'extraordinaire, copiez et collez simplement dans votre éditeur SQL. Utilisez les noms, tailles et types de colonne pour créer une instruction "Créer une table #x [...]" ou "déclarer @x table [...]" que vous pouvez utiliser pour INSÉRER les résultats de la procédure stockée.
Étape 4: insérer dans la table nouvellement créée
Vous allez maintenant avoir une requête qui ressemble aux autres solutions décrites dans ce fil.
Cette technique peut également être utilisée pour convertir une table temporaire (
#temp
) en une variable de table (@temp
). Bien que cela puisse être plus d'étapes que de simplement écrire l'create table
instruction vous-même, cela empêche les erreurs manuelles telles que les fautes de frappe et les incompatibilités de types de données dans les processus volumineux. Le débogage d'une faute de frappe peut prendre plus de temps que l'écriture de la requête en premier lieu.la source
Si l'OPENROWSET vous pose des problèmes, il existe un autre moyen à partir de 2012; utiliser sys.dm_exec_describe_first_result_set_for_object, comme mentionné ici: récupérer les noms de colonne et les types d'une procédure stockée?
Créez d'abord cette procédure stockée pour générer le SQL de la table temporaire:
Pour utiliser la procédure, appelez-la de la manière suivante:
Notez que j'utilise une table temporaire globale. En effet, l'utilisation d'EXEC pour exécuter le SQL dynamique crée sa propre session, de sorte qu'une table temporaire ordinaire serait hors de portée de tout code ultérieur. Si une table temporaire globale pose problème, vous pouvez utiliser une table temporaire ordinaire, mais tout SQL subséquent devra être dynamique, c'est-à-dire également exécuté par l'instruction EXEC.
la source
@SQL
.Quassnoi m'a mis la plupart du chemin là-bas, mais une chose manquait:
**** J'avais besoin d'utiliser des paramètres dans la procédure stockée. ****
Et OPENQUERY ne permet pas que cela se produise:
J'ai donc trouvé un moyen de travailler le système et de ne pas avoir à rendre la définition de table si rigide, et à la redéfinir dans une autre procédure stockée (et bien sûr, prendre le risque qu'elle se casse)!
Oui, vous pouvez créer dynamiquement la définition de table renvoyée par la procédure stockée en utilisant l'instruction OPENQUERY avec de fausses variables (tant que NO RESULT SET renvoie le même nombre de champs et au même emplacement qu'un ensemble de données contenant de bonnes données).
Une fois la table créée, vous pouvez utiliser la procédure stockée exec dans la table temporaire toute la journée.
Et pour noter (comme indiqué ci-dessus), vous devez activer l'accès aux données,
Code:
Merci pour les informations qui ont été fournies à l'origine ... Oui, enfin, je n'ai pas à créer toutes ces définitions de table fausses (strictes) lorsque vous utilisez des données d'une autre procédure stockée ou base de données, et oui, vous pouvez également utiliser des paramètres.
Rechercher des balises de référence:
Procédure stockée SQL 2005 dans la table temporaire
openquery avec procédure stockée et variables 2005
openquery avec des variables
exécuter la procédure stockée dans la table temporaire
Mise à jour: cela ne fonctionnera pas avec les tables temporaires , j'ai donc dû recourir à la création manuelle de la table temporaire.
Avis décevant : cela ne fonctionnera pas avec les tables temporaires , http://www.sommarskog.se/share_data.html#OPENQUERY
Référence: La prochaine chose est de définir LOCALSERVER. Il peut ressembler à un mot-clé dans l'exemple, mais ce n'est en fait qu'un nom. Voici comment procéder:
Pour créer un serveur lié, vous devez avoir l'autorisation ALTER ANY SERVER, ou être membre de l'un des rôles de serveur fixes sysadmin ou setupadmin.
OPENQUERY ouvre une nouvelle connexion à SQL Server. Cela a quelques implications:
La procédure que vous appelez avec OPENQUERY ne peut pas référencer des tables temporaires créées dans la connexion actuelle.
La nouvelle connexion a sa propre base de données par défaut (définie avec sp_addlinkedserver, la valeur par défaut est master), donc toute spécification d'objet doit inclure un nom de base de données.
Si vous avez une transaction ouverte et que vous maintenez des verrous lorsque vous appelez OPENQUERY, la procédure appelée ne peut pas accéder à ce que vous verrouillez. Autrement dit, si vous ne faites pas attention, vous vous bloquerez.
La connexion n'est pas gratuite, il y a donc une pénalité de performance.
la source
SELECT @@SERVERNAME
. Vous pouvez également utiliserEXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
Si vous avez la chance d'avoir SQL 2012 ou supérieur, vous pouvez utiliser
dm_exec_describe_first_result_set_for_object
Je viens de modifier le sql fourni par gotqn. Merci gotqn.
Cela crée une table temporaire globale avec un nom identique à celui de la procédure. La table temporaire peut ensuite être utilisée selon les besoins. N'oubliez pas de le supprimer avant de le réexécuter.
la source
sys.all_objects
plutôt quesys.procedures
si vous voulez le faire pour les procédures stockées intégrées.Ce proc stocké fait le travail:
C'est un léger remaniement de ceci: Insérez les résultats des procédures stockées dans le tableau afin que cela fonctionne réellement.
Si vous voulez qu'il fonctionne avec une table temporaire, vous devrez utiliser une
##GLOBAL
table et la déposer ensuite.la source
Pour insérer le premier jeu d'enregistrements d'une procédure stockée dans une table temporaire, vous devez connaître les éléments suivants:
sp_executesql
)Ce qui précède peut sembler être une limitation, mais à mon humble avis, il est parfaitement logique - si vous utilisez,
sp_executesql
vous pouvez retourner une fois deux colonnes et une fois dix, et si vous avez plusieurs jeux de résultats, vous ne pouvez pas les insérer dans plusieurs tableaux également - vous pouvez insérer un maximum dans deux tables dans une instruction T-SQL (en utilisantOUTPUT
clause et aucun déclencheur).Ainsi, le problème est principalement de savoir comment définir la structure de table temporaire avant d'exécuter l'
EXEC ... INTO ...
instruction.Le premier fonctionne avec
OBJECT_ID
tandis que le second et le troisième fonctionnent également avec les requêtes ad hoc. Je préfère utiliser le DMV au lieu du sp car vous pouvez utiliserCROSS APPLY
et créer les définitions de table temporaires pour plusieurs procédures en même temps.Faites également attention au
system_type_name
domaine car il peut être très utile. Il stocke la définition complète de la colonne. Par exemple:et vous pouvez l'utiliser directement dans la plupart des cas pour créer la définition de table.
Donc, je pense que dans la plupart des cas (si la procédure stockée correspond à certains critères), vous pouvez facilement créer des instructions dynamiques pour résoudre ces problèmes (créer la table temporaire, insérer le résultat de la procédure stockée, faire ce dont vous avez besoin avec les données) .
Notez que les objets ci-dessus ne parviennent pas à définir les premières données du jeu de résultats dans certains cas, comme lorsque des instructions T-SQL dynamiques sont exécutées ou que des tables temporaires sont utilisées dans la procédure stockée.
la source
Maintenant, je sais quel est le résultat de ma procédure, donc j'exécute la requête suivante.
VALEURS (10, 5, 1, NULL) SET IDENTITY_INSERT [dbo]. [TblTestingTree] On
la source
Si la requête ne contient pas de paramètre, utilisez
OpenQuery
else useOpenRowset
.La chose de base serait de créer un schéma selon la procédure stockée et de l'insérer dans cette table. par exemple:
la source
Code
J'espère que ça aide. Veuillez qualifier le cas échéant.
la source
J'ai trouvé Passing Arrays / DataTables dans des procédures stockées qui pourraient vous donner une autre idée de la façon dont vous pourriez résoudre votre problème.
Le lien suggère d'utiliser un paramètre de type Image pour passer à la procédure stockée. Ensuite, dans la procédure stockée, l'image est transformée en une variable de table contenant les données d'origine.
Il y a peut-être un moyen de l'utiliser avec une table temporaire.
la source
J'ai rencontré le même problème et voici ce que j'ai fait pour cela à partir de la suggestion de Paul . La partie principale est ici d'utiliser
NEWID()
pour éviter que plusieurs utilisateurs exécutent les procédures / scripts de magasin en même temps, ce qui est pénible pour la table temporaire globale.la source
Une autre méthode consiste à créer un type et à utiliser PIPELINED pour ensuite renvoyer votre objet. Cela se limite toutefois à connaître les colonnes. Mais il a l'avantage de pouvoir faire:
la source
C'est un processus simple en 2 étapes: - créer une table temporaire - Insérer dans la table temporaire.
Code pour effectuer la même chose:
la source
Après avoir cherché, j'ai trouvé un moyen de créer dynamiquement une table temporaire pour toute procédure stockée sans utiliser
OPENROWSET
ouOPENQUERY
utiliser un schéma générique de la définition de résultat de la procédure stockée, surtout lorsque vous n'êtes pas administrateur de base de données.Le serveur SQL a un proc buit-in
sp_describe_first_result_set
qui peut vous fournir le schéma de n'importe quel jeu de résultats de procédures. J'ai créé une table de schéma à partir des résultats de cette procédure et défini manuellement tout le champ sur NULLABLE.Vous pouvez modifier le schéma de votre version de serveur SQL que vous utilisez (si nécessaire).
la source
Si vous connaissez les paramètres transmis et si vous n'avez pas accès à make sp_configure, modifiez la procédure stockée avec ces paramètres et les mêmes peuvent être stockés dans une table globale ##.
la source
Cela peut être fait dans SQL Server 2014+ à condition que la procédure stockée ne renvoie qu'une seule table. Si quelqu'un trouve un moyen de le faire pour plusieurs tables, j'aimerais en savoir plus.
Cela extrait la définition de la table renvoyée des tables système et l'utilise pour créer la table temporaire pour vous. Vous pouvez ensuite le remplir à partir de la procédure stockée comme indiqué précédemment.
Il existe également des variantes de cela qui fonctionnent également avec Dynamic SQL.
la source
Quelques années de retard à la question, mais j'avais besoin de quelque chose comme ça pour une génération de code rapide et sale. Je pense que comme d'autres l'ont déclaré, il est simplement plus facile de définir la table temporaire à l'avance, mais cette méthode devrait fonctionner pour les requêtes de procédures stockées simples ou les instructions SQL.
Ce sera un peu compliqué, mais il emprunte aux contributeurs ici ainsi qu'à la solution de Paul White de DBA Stack Exchange Obtenez les types de colonnes de résultats de procédure stockée . Encore une fois, pour réitérer cette approche et cet exemple, il n'est pas conçu pour les processus dans un environnement multi-utilisateurs. Dans ce cas, la définition de la table est définie pendant une courte période dans une table temporaire globale pour référence par un processus de modèle de génération de code.
Je n'ai pas entièrement testé cela, il peut donc y avoir des mises en garde, vous pouvez donc aller sur le lien MSDN dans la réponse de Paul White. Cela s'applique à SQL 2012 et supérieur.
Utilisez d'abord la procédure stockée sp_describe_first_result_set qui ressemble à la description d'Oracle.
Cela évaluera la première ligne du premier jeu de résultats, donc si votre procédure stockée ou votre instruction renvoie plusieurs requêtes, elle ne décrira que le premier résultat.
J'ai créé un proc stocké pour décomposer les tâches qui renvoie un seul champ à sélectionner pour créer la définition de la table temporaire.
L'énigme est que vous devez utiliser une table globale, mais vous devez la rendre suffisamment unique pour pouvoir la supprimer et la créer fréquemment sans vous soucier d'une collision.
Dans l'exemple, j'ai utilisé un Guid (FE264BF5_9C32_438F_8462_8A5DC8DEE49E) pour la variable globale remplaçant les tirets par un trait de soulignement
Encore une fois, je ne l'ai testé qu'avec des requêtes de procédure stockée simples et des requêtes simples, de sorte que votre kilométrage peut varier. J'espère que cela aide quelqu'un.
la source
Eh bien, vous devez créer une table temporaire, mais elle n'a pas besoin d'avoir le bon schéma .... J'ai créé une procédure stockée qui modifie une table temporaire existante afin qu'elle ait les colonnes requises avec les bonnes données type et ordre (suppression de toutes les colonnes existantes, ajout de nouvelles colonnes):
Notez que cela ne fonctionnera pas si sys.dm_exec_describe_first_result_set_for_object ne peut pas déterminer les résultats de la procédure stockée (par exemple s'il utilise une table temporaire).
la source
Si vous laissez SQL dynamique créer une table temporaire, cette table appartient à la connexion Dynamic SQL, par opposition à la connexion à partir de laquelle votre procédure stockée est appelée.
Msg 208, niveau 16, état 0 Nom d'objet non valide '#Pivoted'. En effet, #Pivoted appartient à la connexion SQL dynamique. Donc, la dernière instruction
échoue.
Une façon de ne pas faire face à ce problème est de vous assurer que toutes les références à #Pivoted sont faites à l'intérieur de la requête dynamique elle-même:
la source
Je ferais ce qui suit
Créez (convertissez SP en) un UDF (valeur de table UDF).
select * into #tmpBusLine from dbo.UDF_getBusinessLineHistory '16 Mar 2009'
la source