Wie mache ich eine SELECT * INTO [temp table] FROM [stored procedure]
? Nicht FROM [Table]
und ohne zu definieren[temp table]
?
Select
Alle Daten von BusinessLine
in tmpBusLine
funktionieren einwandfrei.
select *
into tmpBusLine
from BusinessLine
Ich versuche das gleiche, aber die Verwendung eines stored procedure
, der Daten zurückgibt, ist nicht ganz dasselbe.
select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'
Ausgabemeldung:
Meldung 156, Ebene 15, Status 1, Zeile 2 Falsche Syntax in der Nähe des Schlüsselworts 'exec'.
Ich habe mehrere Beispiele für das Erstellen einer temporären Tabelle mit derselben Struktur wie die gespeicherte Ausgabeprozedur gelesen, was gut funktioniert, aber es wäre schön, keine Spalten anzugeben.
Antworten:
Sie können hierfür OPENROWSET verwenden . Guck mal. Ich habe auch den Code sp_configure eingefügt, um verteilte Ad-hoc-Abfragen zu aktivieren, falls er noch nicht aktiviert ist.
quelle
Wenn Sie dies tun möchten, ohne zuerst die temporäre Tabelle zu deklarieren, können Sie versuchen, eine benutzerdefinierte Funktion anstelle einer gespeicherten Prozedur zu erstellen und diese benutzerdefinierte Funktion eine Tabelle zurückgeben zu lassen. Wenn Sie die gespeicherte Prozedur verwenden möchten, versuchen Sie alternativ Folgendes:
quelle
In SQL Server 2005 können Sie
INSERT INTO ... EXEC
das Ergebnis einer gespeicherten Prozedur in eine Tabelle einfügen. Aus derINSERT
Dokumentation von MSDN (tatsächlich für SQL Server 2000):quelle
Dies ist eine Antwort auf eine leicht modifizierte Version Ihrer Frage. Wenn Sie die Verwendung einer gespeicherten Prozedur für eine benutzerdefinierte Funktion aufgeben können, können Sie eine benutzerdefinierte Inline-Tabellenwertfunktion verwenden. Dies ist im Wesentlichen eine gespeicherte Prozedur (nimmt Parameter an), die eine Tabelle als Ergebnismenge zurückgibt. und wird daher gut mit einer INTO-Anweisung platziert.
Hier ist ein guter kurzer Artikel darüber und über andere benutzerdefinierte Funktionen. Wenn Sie immer noch einen Fahrbedarf für eine gespeicherte Prozedur haben, können Sie die benutzerdefinierte Inline-Tabellenwertfunktion mit einer gespeicherten Prozedur umschließen. Die gespeicherte Prozedur übergibt nur Parameter, wenn sie select * aus der benutzerdefinierten Inline-Tabellenwertfunktion aufruft.
So hätten Sie beispielsweise eine benutzerdefinierte Inline-Funktion mit Tabellenwert, um eine Liste der Kunden für eine bestimmte Region abzurufen:
Sie können diese Funktion dann aufrufen, um die folgenden Ergebnisse zu erhalten:
Oder um ein SELECT IN zu machen:
Wenn Sie noch eine gespeicherte Prozedur benötigen, wickeln Sie die Funktion als solche ein:
Ich denke, dies ist die Methode ohne Hack, um die gewünschten Ergebnisse zu erzielen. Es verwendet die vorhandenen Funktionen so, wie sie ohne zusätzliche Komplikationen verwendet werden sollten. Durch Verschachteln der benutzerdefinierten Inline-Tabellenwertfunktion in der gespeicherten Prozedur haben Sie auf zwei Arten Zugriff auf die Funktionalität. Plus! Sie haben nur einen Wartungspunkt für den eigentlichen SQL-Code.
Die Verwendung von OPENROWSET wurde vorgeschlagen, aber dies ist nicht das Ziel der OPENROWSET-Funktion (From Books Online):
Die Verwendung von OPENROWSET erledigt die Aufgabe, verursacht jedoch zusätzlichen Aufwand für das Öffnen lokaler Verbindungen und das Marshalling von Daten. Dies ist möglicherweise auch nicht in allen Fällen eine Option, da eine Ad-hoc-Abfrageberechtigung erforderlich ist, die ein Sicherheitsrisiko darstellt und daher möglicherweise nicht erwünscht ist. Der OPENROWSET-Ansatz schließt auch die Verwendung gespeicherter Prozeduren aus, die mehr als eine Ergebnismenge zurückgeben. Dies kann erreicht werden, indem mehrere benutzerdefinierte Inline-Tabellenwertfunktionen in eine einzige gespeicherte Prozedur eingeschlossen werden.
quelle
quelle
Wenn Sie das Schema nicht kennen, können Sie Folgendes tun. Bitte beachten Sie, dass diese Methode schwerwiegende Sicherheitsrisiken birgt.
quelle
Wenn die gespeicherte Prozedur viele Spalten zurückgibt und Sie keine temporäre Tabelle manuell erstellen möchten, um das Ergebnis zu speichern, ist es am einfachsten, in die gespeicherte Prozedur zu gehen und eine "in" -Klausel in die hinzuzufügen letzte select-Anweisung und addiere 1 = 0 zur where-Klausel.
Führen Sie die gespeicherte Prozedur einmal aus und entfernen Sie den soeben hinzugefügten SQL-Code. Jetzt haben Sie eine leere Tabelle, die dem Ergebnis der gespeicherten Prozedur entspricht. Sie können entweder "Skripttabelle als erstellen" für eine temporäre Tabelle erstellen oder einfach direkt in diese Tabelle einfügen.
quelle
SELECT INTO
eine temporäre Tabelle und eine Skripttabelle, wie sie aus der temporären Tabelle erstellt wird? Temp-Tabellen werden in angezeigt,tempdb
aber ich kann keinen Rechtsklick ausführen und kein Erstellungsskript erstellen. Jede Hilfe wird geschätzt.select ... into new_table
implizit eine tatsächliche Tabelle erstellen.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
quelle
Ruft Ihre gespeicherte Prozedur nur die Daten ab oder ändert sie sie auch? Wenn es nur zum Abrufen verwendet wird, können Sie die gespeicherte Prozedur in eine Funktion konvertieren und die Common Table Expressions (CTEs) verwenden, ohne sie wie folgt deklarieren zu müssen:
Was jedoch aus dem CTE abgerufen werden muss, sollte nur in einer Anweisung verwendet werden. Sie können nicht tun
with temp as ...
und versuchen, es nach ein paar Zeilen SQL zu verwenden. Sie können mehrere CTEs in einer Anweisung für komplexere Abfragen haben.Zum Beispiel,
quelle
Wenn die Ergebnistabelle Ihres gespeicherten Prozesses zu kompliziert ist, um die Anweisung "create table" manuell einzugeben, und Sie OPENQUERY OR OPENROWSET nicht verwenden können, können Sie mit sp_help die Liste der Spalten und Datentypen für Sie erstellen. Sobald Sie die Liste der Spalten haben, müssen Sie sie nur noch Ihren Anforderungen entsprechend formatieren.
Schritt 1: Fügen Sie der Ausgabeabfrage "in #temp" hinzu (z. B. "Wählen Sie [...] in [temp aus [...]").
Am einfachsten ist es, die Ausgabeabfrage im Prozess direkt zu bearbeiten. Wenn Sie den gespeicherten Prozess nicht ändern können, können Sie den Inhalt in ein neues Abfragefenster kopieren und die Abfrage dort ändern.
Schritt 2: Führen Sie sp_help in der temporären Tabelle aus. (zB "exec tempdb..sp_help #temp")
Führen Sie nach dem Erstellen der temporären Tabelle sp_help für die temporäre Tabelle aus, um eine Liste der Spalten und Datentypen einschließlich der Größe der Varchar-Felder abzurufen.
Schritt 3: Kopieren Sie die Datenspalten und -typen in eine Anweisung zum Erstellen einer Tabelle
Ich habe eine Excel-Tabelle, mit der ich die Ausgabe von sp_help in eine Anweisung "create table" formatiere. Sie brauchen nichts Besonderes, kopieren Sie es einfach und fügen Sie es in Ihren SQL-Editor ein. Verwenden Sie die Spaltennamen, -größen und -typen, um eine Anweisung "Tabelle #x [...] erstellen" oder "Tabelle @x [...] deklarieren" zu erstellen, mit der Sie die Ergebnisse der gespeicherten Prozedur einfügen können.
Schritt 4: In die neu erstellte Tabelle einfügen
Jetzt haben Sie eine Abfrage, die den anderen in diesem Thread beschriebenen Lösungen entspricht.
Diese Technik kann auch verwendet werden, um eine temporäre Tabelle (
#temp
) in eine Tabellenvariable (@temp
) zu konvertieren . Dies kann mehr als nur das Schreiben dercreate table
Anweisung selbst sein, verhindert jedoch manuelle Fehler wie Tippfehler und Datentypinkongruenzen in großen Prozessen. Das Debuggen eines Tippfehlers kann länger dauern als das Schreiben der Abfrage.quelle
Wenn das OPENROWSET Probleme verursacht, gibt es ab 2012 einen anderen Weg. Verwenden Sie sys.dm_exec_describe_first_result_set_for_object, wie hier erwähnt: Spaltennamen und Typen einer gespeicherten Prozedur abrufen ?
Erstellen Sie zunächst diese gespeicherte Prozedur, um die SQL für die temporäre Tabelle zu generieren:
Um das Verfahren zu verwenden, rufen Sie es folgendermaßen auf:
Beachten Sie, dass ich eine globale temporäre Tabelle verwende. Dies liegt daran, dass die Verwendung von EXEC zum Ausführen des dynamischen SQL eine eigene Sitzung erstellt, sodass eine normale temporäre Tabelle für jeden nachfolgenden Code nicht relevant ist. Wenn eine globale temporäre Tabelle ist ein Problem, Sie können eine gewöhnliche temporäre Tabelle verwenden, aber jede nachfolgende SQL müßte dynamisch sein, das heißt, auch durch die EXEC - Anweisung ausgeführt.
quelle
@SQL
.Quassnoi hat mich den größten Teil des Weges dorthin gebracht, aber eines fehlte:
**** Ich musste Parameter in der gespeicherten Prozedur verwenden. ****
Und OPENQUERY lässt dies nicht zu:
Also habe ich einen Weg gefunden, das System zu arbeiten und muss die Tabellendefinition auch nicht so starr machen und sie in einer anderen gespeicherten Prozedur neu definieren (und natürlich die Chance nutzen, dass sie kaputt geht)!
Ja, Sie können die von der gespeicherten Prozedur zurückgegebene Tabellendefinition mithilfe der Anweisung OPENQUERY mit falschen Variablen dynamisch erstellen (solange NO RESULT SET dieselbe Anzahl von Feldern und dieselbe Position wie ein Dataset mit guten Daten zurückgibt).
Sobald die Tabelle erstellt wurde, können Sie die gespeicherte Prozedur exec den ganzen Tag in der temporären Tabelle verwenden.
Und um zu beachten (wie oben angegeben), müssen Sie den Datenzugriff aktivieren,
Code:
Vielen Dank für die Informationen, die ursprünglich bereitgestellt wurden ... Ja, schließlich muss ich nicht alle diese falschen (strengen) Tabellendefinitionen erstellen, wenn ich Daten aus einer anderen gespeicherten Prozedur oder Datenbank verwende, und ja, Sie können auch Parameter verwenden.
Referenz-Tags suchen:
Gespeicherte SQL 2005-Prozedur in temporäre Tabelle
openquery mit gespeicherter Prozedur und Variablen 2005
openquery mit Variablen
Führen Sie die gespeicherte Prozedur in der temporären Tabelle aus
Update: Dies funktioniert nicht mit temporären Tabellen, daher musste ich die temporäre Tabelle manuell erstellen.
Schade : Dies funktioniert nicht mit temporären Tabellen , http://www.sommarskog.se/share_data.html#OPENQUERY
Referenz: Als nächstes definieren Sie LOCALSERVER. Es mag im Beispiel wie ein Schlüsselwort aussehen, aber es ist tatsächlich nur ein Name. Das ist wie man es macht:
Um einen Verbindungsserver zu erstellen, müssen Sie über die Berechtigung ALTER ANY SERVER verfügen oder Mitglied einer der festen Serverrollen sysadmin oder setupadmin sein.
OPENQUERY öffnet eine neue Verbindung zu SQL Server. Dies hat einige Auswirkungen:
Die Prozedur, die Sie mit OPENQUERY aufrufen, kann nicht auf temporäre Tabellen verweisen, die in der aktuellen Verbindung erstellt wurden.
Die neue Verbindung verfügt über eine eigene Standarddatenbank (definiert mit sp_addlinkedserver, Standard ist master), daher müssen alle Objektspezifikationen einen Datenbanknamen enthalten.
Wenn Sie eine offene Transaktion haben und beim Aufrufen von OPENQUERY Sperren halten, kann die aufgerufene Prozedur nicht auf das zugreifen, was Sie sperren. Das heißt, wenn Sie nicht aufpassen, werden Sie sich selbst blockieren.
Das Verbinden ist nicht kostenlos, daher gibt es einen Leistungsverlust.
quelle
SELECT @@SERVERNAME
. Sie können auchEXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
Wenn Sie das Glück haben, SQL 2012 oder höher zu haben, können Sie verwenden
dm_exec_describe_first_result_set_for_object
Ich habe gerade die von gotqn bereitgestellte SQL bearbeitet. Danke gotqn.
Dadurch wird eine globale temporäre Tabelle mit dem gleichen Namen wie der Prozedurname erstellt. Die temporäre Tabelle kann später nach Bedarf verwendet werden. Vergessen Sie nur nicht, es fallen zu lassen, bevor Sie es erneut ausführen.
quelle
sys.all_objects
anstelle von,sys.procedures
wenn Sie dies für integrierte gespeicherte Prozeduren tun möchten.Dieser gespeicherte Prozess erledigt den Job:
Dies ist eine leichte Überarbeitung: Fügen Sie die Ergebnisse gespeicherter Prozeduren in die Tabelle ein, damit sie tatsächlich funktionieren.
Wenn Sie möchten, dass es mit einer temporären Tabelle funktioniert, müssen Sie eine
##GLOBAL
Tabelle verwenden und anschließend löschen.quelle
Um den ersten Datensatz einer gespeicherten Prozedur in eine temporäre Tabelle einzufügen, müssen Sie Folgendes wissen:
sp_executesql
)Das Obige mag als Einschränkung erscheinen, aber meiner Meinung nach ist es vollkommen sinnvoll - wenn Sie verwenden
sp_executesql
, können Sie einmal zwei Spalten und einmal zehn zurückgeben, und wenn Sie mehrere Ergebnismengen haben, können Sie diese nicht auch in mehrere Tabellen einfügen - Sie können maximal einfügen in zwei Tabellen in einer T-SQL-Anweisung (mitOUTPUT
Klausel und ohne Trigger).Daher geht es hauptsächlich darum, wie die temporäre Tabellenstruktur definiert wird, bevor die
EXEC ... INTO ...
Anweisung ausgeführt wird.Der erste funktioniert mit,
OBJECT_ID
während der zweite und der dritte auch mit Ad-hoc-Abfragen arbeiten. Ich bevorzuge die Verwendung der DMV anstelle der sp, da SieCROSS APPLY
die temporären Tabellendefinitionen für mehrere Prozeduren gleichzeitig verwenden und erstellen können.Achten Sie auch auf das
system_type_name
Feld, da es sehr nützlich sein kann. Es speichert die vollständige Spaltendefinition. Zum Beispiel:In den meisten Fällen können Sie die Tabellendefinition direkt verwenden.
Daher denke ich, dass Sie in den meisten Fällen (wenn die gespeicherte Prozedur bestimmten Kriterien entspricht) problemlos dynamische Anweisungen zur Lösung solcher Probleme erstellen können (erstellen Sie die temporäre Tabelle, fügen Sie das Ergebnis der gespeicherten Prozedur ein, tun Sie, was Sie mit den Daten benötigen). .
Beachten Sie, dass die oben genannten Objekte in einigen Fällen die Daten der ersten Ergebnismenge nicht definieren können, z. B. wenn dynamische T-SQL-Anweisungen ausgeführt werden oder temporäre Tabellen in der gespeicherten Prozedur verwendet werden.
quelle
Jetzt weiß ich, was das Ergebnis meiner Prozedur ist, und führe die folgende Abfrage durch.
VALUES (10, 5, 1, NULL) SET IDENTITY_INSERT [dbo]. [TblTestingTree] On
quelle
Wenn die Abfrage keine Parameter enthält, verwenden Sie
OpenQuery
else useOpenRowset
.Grundlegend wäre, ein Schema gemäß der gespeicherten Prozedur zu erstellen und in diese Tabelle einzufügen. z.B:
quelle
Code
Ich hoffe das hilft. Bitte qualifizieren Sie sich entsprechend.
quelle
Ich habe festgestellt, dass Arrays / DataTables an gespeicherte Prozeduren übergeben werden die Ihnen möglicherweise eine weitere Vorstellung davon geben, wie Sie Ihr Problem lösen können.
Der Link schlägt vor, einen Bildtypparameter zu verwenden, um an die gespeicherte Prozedur zu übergeben. In der gespeicherten Prozedur wird das Bild dann in eine Tabellenvariable umgewandelt, die die Originaldaten enthält.
Vielleicht gibt es eine Möglichkeit, dies mit einer temporären Tabelle zu verwenden.
quelle
Ich bin auf das gleiche Problem gestoßen, und hier ist, was ich dafür aus Pauls Vorschlag heraus getan habe . Der Hauptteil ist hier zu verwenden
NEWID()
, um zu vermeiden, dass mehrere Benutzer die Speicherprozeduren / Skripte gleichzeitig ausführen, der Schmerz für globale temporäre Tabelle.quelle
Eine andere Methode besteht darin, einen Typ zu erstellen und mit PIPELINED Ihr Objekt zurückzugeben. Dies beschränkt sich jedoch darauf, die Spalten zu kennen. Aber es hat den Vorteil, in der Lage zu sein:
quelle
Es ist ein einfacher Prozess in zwei Schritten: - Erstellen einer temporären Tabelle - Einfügen in die temporäre Tabelle.
Code, um dasselbe auszuführen:
quelle
Nachdem ich mich umgesehen hatte, fand ich eine Möglichkeit, eine temporäre Tabelle dynamisch für jede gespeicherte Prozedur zu erstellen, ohne ein generisches Schema der Ergebnisdefinition der gespeicherten Prozedur zu verwenden
OPENROWSET
oder zuOPENQUERY
verwenden, insbesondere wenn Sie kein Datenbankadministrator sind.Der SQL Server verfügt über einen integrierten Prozess
sp_describe_first_result_set
, der Ihnen ein Schema für jede Prozedur-Ergebnismenge bereitstellen kann. Ich habe aus den Ergebnissen dieser Prozedur eine Schematabelle erstellt und das gesamte Feld manuell auf NULLABLE gesetzt.Sie können das Schema für Ihre verwendete SQL Server-Version anpassen (falls erforderlich).
quelle
Wenn Sie die Parameter kennen, die übergeben werden, und wenn Sie keinen Zugriff auf sp_configure haben, bearbeiten Sie die gespeicherte Prozedur mit diesen Parametern. Diese können in einer globalen Tabelle ## gespeichert werden.
quelle
Dies ist in SQL Server 2014+ möglich, sofern die gespeicherte Prozedur nur eine Tabelle zurückgibt. Wenn jemand einen Weg findet, dies für mehrere Tische zu tun, würde ich gerne davon erfahren.
Dadurch wird die Definition der zurückgegebenen Tabelle aus den Systemtabellen abgerufen und damit die temporäre Tabelle für Sie erstellt. Sie können es dann wie zuvor angegeben aus der gespeicherten Prozedur füllen.
Es gibt auch Varianten davon, die auch mit Dynamic SQL funktionieren.
quelle
Ein paar Jahre zu spät zur Frage, aber ich brauchte so etwas für eine schnelle und schmutzige Codegenerierung. Ich glaube, wie andere gesagt haben, ist es einfacher, die temporäre Tabelle im Voraus zu definieren, aber diese Methode sollte für einfache Abfragen gespeicherter Prozeduren oder SQL-Anweisungen funktionieren.
Dies wird ein wenig kompliziert sein, aber es leiht sich von den Mitwirkenden hier sowie von Paul Whites Lösung von DBA Stack Exchange Get gespeicherte Prozedur-Ergebnisspaltentypen aus . Um diesen Ansatz zu wiederholen, ist das Beispiel nicht für Prozesse in einer Mehrbenutzerumgebung konzipiert. In diesem Fall wird die Tabellendefinition für eine kurze Zeit in einer globalen temporären Tabelle als Referenz für einen Codegenerierungsvorlagenprozess festgelegt.
Ich habe dies noch nicht vollständig getestet, daher kann es zu Einschränkungen kommen, sodass Sie möglicherweise auf den MSDN-Link in Paul Whites Antwort zugreifen möchten. Dies gilt für SQL 2012 und höher.
Verwenden Sie zuerst die gespeicherte Prozedur sp_describe_first_result_set, die der Beschreibung von Oracle ähnelt.
Dadurch wird die erste Zeile der ersten Ergebnismenge ausgewertet. Wenn Ihre gespeicherte Prozedur oder Anweisung mehrere Abfragen zurückgibt, wird nur das erste Ergebnis beschrieben.
Ich habe einen gespeicherten Prozess erstellt, um die Aufgaben aufzuschlüsseln, die ein einzelnes Feld zur Auswahl zurückgeben, um die temporäre Tabellendefinition zu erstellen.
Das Rätsel ist, dass Sie eine globale Tabelle verwenden müssen, diese jedoch so eindeutig machen müssen, dass Sie sie häufig löschen und erstellen können, ohne sich um eine Kollision sorgen zu müssen.
Im Beispiel habe ich eine Guid (FE264BF5_9C32_438F_8462_8A5DC8DEE49E) für die globale Variable verwendet, die die Bindestriche durch Unterstriche ersetzt
Auch hier habe ich es nur mit einfachen Abfragen für gespeicherte Prozeduren und einfachen Abfragen getestet, sodass Ihr Kilometerstand variieren kann. Hoffe das hilft jemandem.
quelle
Nun, Sie müssen eine temporäre Tabelle erstellen, aber sie muss nicht das richtige Schema haben. Ich habe eine gespeicherte Prozedur erstellt, die eine vorhandene temporäre Tabelle so ändert, dass sie die erforderlichen Spalten mit den richtigen Daten enthält Typ und Reihenfolge (Löschen aller vorhandenen Spalten, Hinzufügen neuer Spalten):
Beachten Sie, dass dies nicht funktioniert, wenn sys.dm_exec_describe_first_result_set_for_object die Ergebnisse der gespeicherten Prozedur nicht ermitteln kann (z. B. wenn eine temporäre Tabelle verwendet wird).
quelle
Wenn Sie Dynamic SQL eine temporäre Tabelle erstellen lassen, gehört diese Tabelle der Dynamic SQL-Verbindung, im Gegensatz zu der Verbindung, von der aus Ihre gespeicherte Prozedur aufgerufen wird.
Meldung 208, Ebene 16, Status 0 Ungültiger Objektname '#Pivoted'. Dies liegt daran, dass #Pivoted der Dynamic SQL-Verbindung gehört. Also die letzte Anweisung
schlägt fehl.
Eine Möglichkeit, dieses Problem nicht zu lösen, besteht darin, sicherzustellen, dass alle Verweise auf #Pivoted aus der dynamischen Abfrage selbst stammen:
quelle
Ich würde folgendes tun
Erstellen Sie eine UDF (konvertieren Sie SP in) (Tabellenwert UDF).
select * into #tmpBusLine from dbo.UDF_getBusinessLineHistory '16 Mar 2009'
quelle