it-swarm.com.de

Fügen Sie die Ergebnisse einer gespeicherten Prozedur in eine temporäre Tabelle ein

Wie mache ich einen SELECT * INTO [temp table] FROM [stored procedure]? Nicht FROM [Table] und ohne [temp table] zu definieren?

Select Alle Daten von BusinessLine bis tmpBusLine funktionieren einwandfrei.

select *
into tmpBusLine
from BusinessLine

Ich versuche dasselbe, aber die Verwendung eines stored procedure, der Daten zurückgibt, ist nicht ganz dasselbe.

select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'

Ausgangsnachricht:

Meldung 156, Ebene 15, Status 1, Zeile 2 Falsche Syntax in der Nähe des Schlüsselworts 'exec'.

Ich habe mehrere Beispiele zum Erstellen einer temporären Tabelle mit der gleichen Struktur wie die gespeicherte Ausgabeprozedur gelesen, was gut funktioniert, aber es wäre schön, keine Spalten anzugeben.

1491
Ferdeen

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.

CREATE PROC getBusinessLineHistory
AS
BEGIN
    SELECT * FROM sys.databases
END
GO

sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO

SELECT * INTO #MyTempTable FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC getBusinessLineHistory')

SELECT * FROM #MyTempTable
676
Aaron Alton

Wenn Sie dies tun möchten, ohne zuvor die temporäre Tabelle deklariert zu haben, 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 alternativ die gespeicherte Prozedur verwenden möchten, versuchen Sie Folgendes:

CREATE TABLE #tmpBus
(
   COL1 INT,
   COL2 INT
)

INSERT INTO #tmpBus
Exec SpGetRecords 'Params'
580
Gavin

In SQL Server 2005 können Sie INSERT INTO ... EXEC verwenden, um das Ergebnis einer gespeicherten Prozedur in eine Tabelle einzufügen. Aus MSDNs INSERT Dokumentation (tatsächlich für SQL Server 2000):

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
282
Matt Hamilton

Dies ist eine Antwort auf eine leicht geänderte Version Ihrer Frage. Wenn Sie auf die Verwendung einer gespeicherten Prozedur für eine benutzerdefinierte Funktion verzichten können, können Sie eine benutzerdefinierte Inline-Tabellenfunktion verwenden. Dies ist im Wesentlichen eine gespeicherte Prozedur (die Parameter akzeptiert), die eine Tabelle als Ergebnismenge zurückgibt. und wird daher gut mit einer INTO-Anweisung platziert.

Hier ist ein guter schneller Artikel dazu und zu anderen benutzerdefinierten Funktionen. Wenn Sie weiterhin eine gespeicherte Prozedur benötigen, können Sie die benutzerdefinierte Inline-Tabellenwertfunktion mit einer gespeicherten Prozedur verbinden. Die gespeicherte Prozedur übergibt nur Parameter, wenn sie select * aus der benutzerdefinierten Inline-Tabellenwertfunktion aufruft.

So hätten Sie beispielsweise eine benutzerdefinierte Inline-Tabellenfunktion, um eine Liste der Kunden für eine bestimmte Region abzurufen:

CREATE FUNCTION CustomersByRegion 
(  
    @RegionID int  
)
RETURNS TABLE 
AS
RETURN 
  SELECT *
  FROM customers
  WHERE RegionID = @RegionID
GO

Sie können diese Funktion dann aufrufen, um Ihre Ergebnisse wie folgt zu ermitteln:

SELECT * FROM CustomersbyRegion(1)

Oder machen Sie ein SELECT INTO:

SELECT * INTO CustList FROM CustomersbyRegion(1)

Wenn Sie noch eine gespeicherte Prozedur benötigen, schließen Sie die Funktion als solche ab:

CREATE PROCEDURE uspCustomersByRegion 
(  
    @regionID int  
)
AS
BEGIN
     SELECT * FROM CustomersbyRegion(@regionID);
END
GO

Ich denke, dies ist die am wenigsten hackende Methode, um die gewünschten Ergebnisse zu erzielen. Dabei werden die vorhandenen Funktionen so verwendet, wie sie ohne zusätzliche Komplikationen verwendet werden sollten. Durch Verschachteln der benutzerdefinierten Inline-Tabellenfunktion in die gespeicherte 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, jedoch ist dies nicht das Ziel der OPENROWSET-Funktion (aus der Onlinedokumentation):

Enthält alle Verbindungsinformationen, die für den Zugriff auf Remotedaten aus einer OLE DB-Datenquelle erforderlich sind. Diese Methode ist eine Alternative zum Zugriff auf Tabellen in einem Verbindungsserver und eine einmalige Ad-hoc-Methode zum Verbinden und Zugreifen auf Remotedaten mithilfe von OLE DB. Verwenden Sie für häufigere Verweise auf OLE DB-Datenquellen stattdessen Verbindungsserver.

Mit OPENROWSET wird die Aufgabe erledigt, es entsteht jedoch ein zusätzlicher Aufwand für das Öffnen lokaler Verbindungen und das Sammeln von Daten. Dies ist möglicherweise auch nicht in allen Fällen eine Option, da eine Ad-hoc-Abfrageerlaubnis erforderlich ist, die ein Sicherheitsrisiko darstellt und daher möglicherweise nicht erwünscht ist. Außerdem schließt der OPENROWSET-Ansatz die Verwendung von gespeicherten 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.

186
Christian Loris
EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE

SELECT  *
INTO    #tmpTable
FROM    OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')
124
Quassnoi

Einfachste Lösung:

CREATE TABLE #temp (...);

INSERT INTO #temp
EXEC [sproc];

Wenn Sie das Schema nicht kennen, können Sie Folgendes tun. Bitte beachten Sie, dass diese Methode schwerwiegende Sicherheitsrisiken birgt.

SELECT * 
INTO #temp
FROM OPENROWSET('SQLNCLI', 
                'Server=localhost;Trusted_Connection=yes;', 
                'EXEC [db].[schema].[sproc]')
117
Tigerjz32

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 meiner Ansicht nach am einfachsten, in die gespeicherte Prozedur zu wechseln und eine "into" -Klausel in der einzufügen letzte select-Anweisung und füge 1 = 0 zur where-Klausel hinzu.

Führen Sie die gespeicherte Prozedur einmal aus, und entfernen Sie den soeben hinzugefügten SQL-Code. Jetzt haben Sie eine leere Tabelle, die mit dem Ergebnis der gespeicherten Prozedur übereinstimmt. Sie können entweder "Skripttabelle als Erstellung" für eine temporäre Tabelle oder einfach direkt in diese Tabelle einfügen.

98
dotjoe
declare @temp table
(
    name varchar(255),
    field varchar(255),
    filename varchar(255),
    filegroup varchar(255),
    size varchar(255),
    maxsize varchar(255),
    growth varchar(255),
    usage varchar(255)
);
INSERT @temp  Exec sp_helpfile;
select * from @temp;
65
nitin

Wenn die Ergebnistabelle Ihres gespeicherten Prozesses zu kompliziert ist, um die Anweisung "create table" von Hand einzugeben, und Sie OPENQUERY OR OPENROWSET nicht verwenden können, können Sie sp_help verwenden, um die Liste der Spalten und zu generieren Datentypen für Sie. Sobald Sie die Liste der Spalten haben, müssen Sie sie nur noch entsprechend Ihren Anforderungen formatieren.

Schritt 1: Fügen Sie der Ausgabeabfrage "into #temp" hinzu (z. B. "select [...] into #temp from [...]").

Am einfachsten ist es, die Ausgabeabfrage direkt im proc zu bearbeiten. Wenn Sie den gespeicherten Vorgang 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 für die temporäre Tabelle aus. (z. B. "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 "Create table #x" [...] oder "declare @x table [...]" 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.

DECLARE @t TABLE 
(
   --these columns were copied from sp_help
   COL1 INT,
   COL2 INT   
)

INSERT INTO @t 
Exec spMyProc 

Diese Technik kann auch zum Konvertieren einer temporären Tabelle (#temp) in eine Tabellenvariable (@temp) verwendet werden. Dies kann mehr sein als nur das Schreiben der Anweisung create table selbst, es verhindert jedoch manuelle Fehler wie Tippfehler und Datentypenkonflikte in großen Prozessen. Das Debuggen eines Tippfehlers kann mehr Zeit in Anspruch nehmen als das erstmalige Schreiben der Abfrage.

46
FistOfFury

Ruft Ihre gespeicherte Prozedur nur die Daten ab oder ändert sie auch? Wenn es nur zum Abrufen verwendet wird, können Sie die gespeicherte Prozedur in eine Funktion konvertieren und die allgemeinen Tabellenausdrücke (Common Table Expressions, CTEs) verwenden, ohne sie wie folgt deklarieren zu müssen:

with temp as (
    select * from dbo.fnFunctionName(10, 20)
)
select col1, col2 from temp

Was auch immer vom CTE abgerufen werden muss, sollte nur in einer Anweisung verwendet werden. Sie können einen with temp as ... nicht ausführen und versuchen, ihn nach einigen SQL-Zeilen zu verwenden. Für komplexere Abfragen können Sie mehrere CTEs in einer Anweisung haben.

Zum Beispiel,

with temp1020 as (
    select id from dbo.fnFunctionName(10, 20)
),
temp2030 as (
    select id from dbo.fnFunctionName(20, 30)
)
select * from temp1020 
where id not in (select id from temp2030)
46
Rashmi Pandit

Quassnoi hat mich meistens dorthin gebracht, aber eines hat gefehlt:

**** Ich musste Parameter in der gespeicherten Prozedur verwenden. ****

Und OPENQUERY lässt dies nicht zu:

Also habe ich einen Weg gefunden, das System zu bearbeiten und auch die Tabellendefinition nicht so starr zu machen und sie in einer anderen gespeicherten Prozedur neu zu definieren (und natürlich die Möglichkeit zu nutzen, dass sie kaputt geht)!

Ja, Sie können die von der gespeicherten Prozedur zurückgegebene Tabellendefinition dynamisch erstellen, indem Sie die OPENQUERY-Anweisung mit falschen Variablen verwenden (sofern das NO RESULT SET die gleiche Anzahl von Feldern und im zurückgibt gleiche Position wie ein Datensatz mit guten Daten).

Sobald die Tabelle erstellt ist, können Sie die gespeicherte Prozedur exec den ganzen Tag lang in der temporären Tabelle verwenden.


Und um (wie oben angegeben) zu beachten, müssen Sie den Datenzugriff aktivieren,

EXEC sp_serveroption 'MYSERVERNAME', 'DATA ACCESS', TRUE

Code:

declare @locCompanyId varchar(8)
declare @locDateOne datetime
declare @locDateTwo datetime

set @locDateOne = '2/11/2010'
set @locDateTwo = getdate()

--Build temporary table (based on bogus variable values)
--because we just want the table definition and
--since openquery does not allow variable definitions...
--I am going to use bogus variables to get the table defintion.

select * into #tempCoAttendanceRpt20100211
FROM OPENQUERY(DBASESERVER,
  'EXEC DATABASE.dbo.Proc_MyStoredProc 1,"2/1/2010","2/15/2010 3:00 pm"')

set @locCompanyId = '7753231'

insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo

set @locCompanyId = '9872231'

insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo

select * from #tempCoAttendanceRpt20100211
drop table #tempCoAttendanceRpt20100211

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 verwende eine andere gespeicherte Prozedur oder Datenbank, 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.

Scherzbemerkung : 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, ist aber in Wirklichkeit nur ein Name. Das ist wie man es macht:

sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                   @provider = 'SQLOLEDB', @datasrc = @@servername

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), sodass alle Objektspezifikationen einen Datenbanknamen enthalten müssen.

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, blockieren Sie sich.

Das Verbinden ist nicht kostenlos, daher gibt es eine Leistungsstrafe.

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 Prozedur zu generieren

CREATE PROCEDURE dbo.usp_GetStoredProcTableDefinition(
    @ProcedureName  nvarchar(128),
    @TableName      nvarchar(128),
    @SQL            nvarchar(max) OUTPUT
)
AS
SET @SQL = 'CREATE TABLE ' + @tableName + ' ('

SELECT @SQL = @SQL + '['+name +'] '+ system_type_name +''  + ','
        FROM sys.dm_exec_describe_first_result_set_for_object
        (
          OBJECT_ID(@ProcedureName), 
          NULL
        );

--Remove trailing comma
SET @SQL = SUBSTRING(@SQL,0,LEN(@SQL))    
SET @SQL =  @SQL +')'

Rufen Sie die Prozedur folgendermaßen auf, um sie zu verwenden:

DECLARE     @SQL    NVARCHAR(MAX)

exec dbo.usp_GetStoredProcTableDefinition
    @ProcedureName='dbo.usp_YourProcedure',
    @TableName='##YourGlobalTempTable',@SQL = @SQL OUTPUT

INSERT INTO ##YourGlobalTempTable
EXEC    [dbo].usp_YourProcedure

select * from ##YourGlobalTempTable

Beachten Sie, dass ich eine globale temporäre Tabelle verwende. Dies liegt daran, dass die Verwendung von EXEC zum Ausführen von dynamischem SQL eine eigene Sitzung erstellt, sodass eine gewöhnliche temporäre Tabelle für nachfolgenden Code nicht mehr gültig ist. Wenn eine globale temporäre Tabelle ein Problem darstellt, können Sie eine normale temporäre Tabelle verwenden , aber alle nachfolgenden SQL-Anweisungen müssen dynamisch sein, dh auch ausgeführt werden durch die EXEC-Anweisung.

27
StuartQ

Dieser gespeicherte Prozess erledigt die Arbeit:

CREATE PROCEDURE [dbo].[ExecIntoTable]
(
    @tableName          NVARCHAR(256),
    @storedProcWithParameters   NVARCHAR(MAX)
)
AS
BEGIN
    DECLARE @driver         VARCHAR(10)
    DECLARE @connectionString   NVARCHAR(600)
    DECLARE @sql            NVARCHAR(MAX)
    DECLARE @rowsetSql      NVARCHAR(MAX)

    SET @driver = '''SQLNCLI'''

    SET @connectionString = 
        '''server=' + 
            CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)) + 
            COALESCE('\' + CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(256)), '') + 
        ';trusted_connection=yes'''

    SET @rowsetSql = '''EXEC ' + REPLACE(@storedProcWithParameters, '''', '''''') + ''''

    SET @sql = '
SELECT
    *
INTO 
    ' + @tableName + ' 
FROM
    OPENROWSET(' + @driver + ',' + @connectionString + ',' + @rowsetSql + ')'

    EXEC (@sql)
END
GO

Dies ist eine leichte Überarbeitung: Ergebnisse gespeicherter Prozeduren in Tabelle einfügen damit es tatsächlich funktioniert.

Wenn Sie möchten, dass es mit einer temporären Tabelle funktioniert, müssen Sie eine ##GLOBAL -Tabelle verwenden und diese anschließend löschen.

22
briantyler

Wenn Sie das Glück haben, SQL 2012 oder höher zu haben, können Sie dm_exec_describe_first_result_set_for_object verwenden.

Ich habe gerade den von gotqn bereitgestellten SQL-Code bearbeitet. Danke, gotqn.

Dadurch wird eine globale temporäre Tabelle mit demselben Namen wie der Prozedurname erstellt. Die temporäre Tabelle kann später nach Bedarf verwendet werden. Vergiss nur nicht, es fallen zu lassen, bevor du es erneut ausführst.

    declare @procname nvarchar(255) = 'myProcedure',
            @sql nvarchar(max) 

    set @sql = 'create table ##' + @procname + ' ('
    begin
            select      @sql = @sql + '[' + r.name + '] ' +  r.system_type_name + ','
            from        sys.procedures AS p
            cross apply sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r
            where       p.name = @procname

            set @sql = substring(@sql,1,len(@sql)-1) + ')'
            execute (@sql)
            execute('insert ##' + @procname + ' exec ' + @procname)
    end
20
Sandeep Gaadhe
  1. Ich erstelle eine Tabelle mit dem folgenden Schema und Daten.
  2. Erstellen Sie eine gespeicherte Prozedur.
  3. Jetzt weiß ich, was das Ergebnis meiner Prozedur ist, und führe die folgende Abfrage durch.

    CREATE TABLE [dbo].[tblTestingTree](
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [ParentId] [int] NULL,
        [IsLeft] [bit] NULL,
        [IsRight] [bit] NULL,
    CONSTRAINT [PK_tblTestingTree] PRIMARY KEY CLUSTERED
    (
        [Id] ASC
    ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    SET IDENTITY_INSERT [dbo].[tblTestingTree] ON
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (1, NULL, NULL, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (2, 1, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (3, 1, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (4, 2, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (5, 2, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (6, 3, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (7, 3, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (8, 4, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (9, 4, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (10, 5, 1, NULL)
    
    SET IDENTITY_INSERT [dbo].[tblTestingTree] OFF
    

    VALUES (10, 5, 1, NULL) SET IDENTITY_INSERT [dbo]. [TblTestingTree] On

    create procedure GetDate
    as
    begin
        select Id,ParentId from tblTestingTree
    end
    
    create table tbltemp
    (
        id int,
        ParentId int
    )
    insert into tbltemp
    exec GetDate
    
    select * from tbltemp;
    
17
Devansh

Um den ersten Datensatz einer gespeicherten Prozedur in eine temporäre Tabelle einzufügen, müssen Sie Folgendes wissen:

  1. nur der erste Zeilensatz der gespeicherten Prozedur kann in eine temporäre Tabelle eingefügt werden
  2. die gespeicherte Prozedur darf keine dynamische T-SQL-Anweisung (sp_executesql) ausführen.
  3. sie müssen zuerst die Struktur der temporären Tabelle definieren

Das Obige mag einschränkend aussehen, aber meiner Meinung nach macht es durchaus Sinn - wenn Sie sp_executesql verwenden, können Sie einmal zwei Spalten und einmal zehn zurückgeben, und wenn Sie mehrere Ergebnismengen haben, können Sie sie nicht auch in mehrere Tabellen einfügen - Sie können maximal zwei Tabellen in eine T-SQL-Anweisung einfügen (mit der OUTPUT -Klausel und ohne Trigger).

Es geht also hauptsächlich darum, wie die temporäre Tabellenstruktur definiert wird, bevor die Anweisung EXEC ... INTO ... ausgeführt wird.

Der erste arbeitet mit OBJECT_ID, während der zweite und der dritte auch mit Ad-hoc-Abfragen arbeiten. Ich bevorzuge die Verwendung von DMV anstelle von sp, da Sie CROSS APPLY verwenden und die temporären Tabellendefinitionen für mehrere Prozeduren gleichzeitig erstellen können.

SELECT p.name, r.* 
FROM sys.procedures AS p
CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r;

Achten Sie auch auf das Feld system_type_name, da es sehr nützlich sein kann. Es speichert die vollständige Definition der Spalte. Zum Beispiel:

smalldatetime
nvarchar(max)
uniqueidentifier
nvarchar(1000)
real
smalldatetime
decimal(18,2)

und Sie können es in den meisten Fällen direkt verwenden, um die Tabellendefinition zu erstellen.

Daher denke ich, dass Sie in den meisten Fällen (wenn die gespeicherte Prozedur bestimmten Kriterien entspricht) auf einfache Weise dynamische Anweisungen zum Lösen 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 obigen Objekte in einigen Fällen , in denen dynamische T-SQL-Anweisungen ausgeführt oder temporäre Tabellen verwendet werden, die Daten der ersten Ergebnismenge nicht definieren können die gespeicherte Prozedur.

16
gotqn

Wenn die Abfrage keinen Parameter enthält, verwenden Sie OpenQuery, andernfalls OpenRowset.

Grundlegend wäre, ein Schema gemäß der gespeicherten Prozedur zu erstellen und in diese Tabelle einzufügen. z.B.:

DECLARE @abc TABLE(
                  RequisitionTypeSourceTypeID INT
                , RequisitionTypeID INT
                , RequisitionSourcingTypeID INT
                , AutoDistOverride INT
                , AllowManagerToWithdrawDistributedReq INT
                , ResumeRequired INT
                , WarnSupplierOnDNRReqSubmission  INT
                , MSPApprovalReqd INT
                , EnableMSPSupplierCounterOffer INT
                , RequireVendorToAcceptOffer INT
                , UseCertification INT
                , UseCompetency INT
                , RequireRequisitionTemplate INT
                , CreatedByID INT
                , CreatedDate DATE
                , ModifiedByID INT
                , ModifiedDate DATE
                , UseCandidateScheduledHours INT
                , WeekEndingDayOfWeekID INT
                , AllowAutoEnroll INT
                )
INSERT INTO @abc
EXEC [dbo].[usp_MySp] 726,3
SELECT * FROM @abc
15
ProblemSolver

Code

CREATE TABLE #T1
(
    col1 INT NOT NULL,
    col2 NCHAR(50) NOT NULL,
    col3 TEXT NOT NULL,
    col4 DATETIME NULL,
    col5 NCHAR(50) NULL,
    col6 CHAR(2) NULL,
    col6 NCHAR(100) NULL,
    col7 INT NULL,
    col8 NCHAR(50) NULL,
    col9 DATETIME NULL,
    col10 DATETIME NULL
)

DECLARE @Para1 int
DECLARE @Para2 varchar(32)
DECLARE @Para3 varchar(100)
DECLARE @Para4 varchar(15)
DECLARE @Para5 varchar (12)
DECLARE @Para6 varchar(1)
DECLARE @Para7 varchar(1)


SET @Para1 = 1025
SET @Para2 = N'6as54fsd56f46sd4f65sd'
SET @Para3 = N'XXXX\UserName'
SET @Para4 = N'127.0.0.1'
SET @Para5 = N'XXXXXXX'
SET @Para6 = N'X'
SET @Para7 = N'X'

INSERT INTO #T1
(
    col1,
    col2,
    col3,
    col4,
    col5,
    col6,
    col6,
    col7,
    col8,
    col9,
    col10,
)
EXEC [dbo].[usp_ProcedureName] @Para1, @Para2, @Para3, @Para4, @Para5, @Para6, @Para6

Ich hoffe das hilft. Bitte entsprechend qualifizieren.

12
SoftwareARM

Ich habe Übergeben von Arrays/Datentabellen an gespeicherte Prozeduren gefunden, das Ihnen möglicherweise eine andere Vorstellung davon gibt, wie Sie Ihr Problem lösen können.

Der Link schlägt vor, einen Parameter vom Typ Image für die Übergabe an die gespeicherte Prozedur zu verwenden. In der gespeicherten Prozedur wird das Bild dann in eine Tabellenvariable umgewandelt, die die Originaldaten enthält.

Vielleicht gibt es eine Möglichkeit, wie dies mit einer temporären Tabelle verwendet werden kann.

11
kevchadders

Ich bin auf dasselbe Problem gestoßen, und hier ist, was ich dafür getan habe Vorschlag von Paul . Der Hauptteil besteht darin, NEWID() zu verwenden, um zu vermeiden, dass mehrere Benutzer gleichzeitig die Speicherprozeduren/Skripte ausführen, was die globale temporäre Tabelle schmerzt.

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 + ']')
10
zhongxiao37

Eine andere Methode besteht darin, einen Typ zu erstellen und PIPELINED zu verwenden, um dann Ihr Objekt zurückzusenden. Dies beschränkt sich jedoch auf die Kenntnis der Spalten. Aber es hat den Vorteil, in der Lage zu sein:

SELECT * 
FROM TABLE(CAST(f$my_functions('8028767') AS my_tab_type))
9
pierre

Nachdem ich mich umgesehen hatte, fand ich eine Möglichkeit, eine temporäre Tabelle dynamisch für jede gespeicherte Prozedur zu erstellen, ohne OPENROWSET oder OPENQUERY unter Verwendung eines generischen Schemas der Ergebnisdefinition der gespeicherten Prozedur zu verwenden, insbesondere wenn Sie kein Datenbankadministrator sind.

SQL Server verfügt über einen integrierten Prozess sp_describe_first_result_set, mit dem Sie das Schema aller Ergebnismengen von Prozeduren anzeigen können. Aus den Ergebnissen dieser Prozedur habe ich eine Schematabelle erstellt und das gesamte Feld manuell auf NULLABLE gesetzt.

declare @procname varchar(100) = 'PROCEDURENAME' -- your procedure name
declare @param varchar(max) = '''2019-06-06''' -- your parameters 
declare @execstr nvarchar(max) = N'exec ' + @procname
declare @qry nvarchar(max)

-- Schema table to store the result from sp_describe_first_result_set.
create table #d
(is_hidden  bit  NULL, column_ordinal   int  NULL, name sysname NULL, is_nullable   bit  NULL, system_type_id   int  NULL, system_type_name nvarchar(256) NULL,
max_length  smallint  NULL, precision   tinyint  NULL,  scale   tinyint  NULL,  collation_name  sysname NULL, user_type_id  int NULL, user_type_database    sysname NULL,
user_type_schema    sysname NULL,user_type_name sysname NULL,Assembly_qualified_type_name   nvarchar(4000),xml_collection_id    int NULL,xml_collection_database    sysname NULL,
xml_collection_schema   sysname NULL,xml_collection_name    sysname NULL,is_xml_document    bit  NULL,is_case_sensitive bit  NULL,is_fixed_length_clr_type  bit  NULL,
source_server   sysname NULL,source_database    sysname NULL,source_schema  sysname NULL,source_table   sysname NULL,source_column  sysname NULL,is_identity_column bit NULL,
is_part_of_unique_key   bit NULL,is_updateable  bit NULL,is_computed_column bit NULL,is_sparse_column_set   bit NULL,ordinal_in_order_by_list   smallint NULL,
order_by_list_length    smallint NULL,order_by_is_descending    smallint NULL,tds_type_id   int  NULL,tds_length    int  NULL,tds_collation_id  int NULL,
tds_collation_sort_id   tinyint NULL)


-- Get result set definition of your procedure
insert into #d
EXEC sp_describe_first_result_set @exestr, NULL, 0

-- Create a query to generate and populate a global temp table from above results
select 
@qry = 'Create table ##t(' +
stuff(  
    (select ',' + name + ' '+ system_type_name + ' NULL'
    from #d d For XML Path, TYPE)
    .value(N'.[1]', N'nvarchar(max)')
, 1,1,'')
+ ')

insert into ##t 
Exec '[email protected]+' ' + @param

Exec sp_executesql @qry

-- Use below global temp table to query the data as you may
select * from ##t

-- **WARNING** Don't forget to drop the global temp table ##t.
--drop table ##t
drop table #d 

Entwickelt und getestet auf SQL Server Version - Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (Build 17134 :)

Sie können das Schema für Ihre verwendete SQL Server-Version optimieren (falls erforderlich).

6
vendettamit

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, und dieselbe kann in einer ## globalen Tabelle gespeichert werden.

4
lakshmivisalij

Dies ist ein einfacher Vorgang in zwei Schritten: - Erstellen einer temporären Tabelle - Einfügen in die temporäre Tabelle.

Code, um dasselbe auszuführen:

CREATE TABLE #tempTable (Column1 int, Column2 varchar(max));
INSERT INTO #tempTable 
EXEC [app].[Sproc_name]
@param1 = 1,
@param2 =2;
3
S Krishna

Nun, Sie müssen eine temporäre Tabelle erstellen, sie muss jedoch 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):

GO
create procedure #TempTableForSP(@tableId int, @procedureId int)  
as   
begin  
    declare @tableName varchar(max) =  (select name  
                                        from tempdb.sys.tables 
                                        where object_id = @tableId
                                        );    
    declare @tsql nvarchar(max);    
    declare @tempId nvarchar(max) = newid();      
    set @tsql = '    
    declare @drop nvarchar(max) = (select  ''alter table tempdb.dbo.' + @tableName 
            +  ' drop column ''  + quotename(c.name) + '';''+ char(10)  
                                   from tempdb.sys.columns c   
                                   where c.object_id =  ' + 
                                         cast(@tableId as varchar(max)) + '  
                                   for xml path('''')  
                                  )    
    alter table tempdb.dbo.' + @tableName + ' add ' + QUOTENAME(@tempId) + ' int;
    exec sp_executeSQL @drop;    
    declare @add nvarchar(max) = (    
                                select ''alter table ' + @tableName 
                                      + ' add '' + name 
                                      + '' '' + system_type_name 
                           + case when d.is_nullable=1 then '' null '' else '''' end 
                                      + char(10)   
                              from sys.dm_exec_describe_first_result_set_for_object(' 
                               + cast(@procedureId as varchar(max)) + ', 0) d  
                                order by column_ordinal  
                                for xml path(''''))    

    execute sp_executeSQL  @add;    
    alter table '  + @tableName + ' drop column ' + quotename(@tempId) + '  ';      
    execute sp_executeSQL @tsql;  
end         
GO

create table #exampleTable (pk int);

declare @tableId int = object_Id('tempdb..#exampleTable')
declare @procedureId int = object_id('examplestoredProcedure')

exec #TempTableForSP @tableId, @procedureId;

insert into #exampleTable
exec examplestoredProcedure

Hinweis Dies funktioniert nicht, 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).

1
jmoreno

Dies ist in SQL Server 2014+ möglich, sofern SP nur eine Tabelle zurückgibt. Wenn jemand einen Weg findet, dies für mehrere Tabellen zu tun, würde ich gerne davon erfahren.

DECLARE @storeProcname NVARCHAR(MAX) = ''

SET @storeProcname = 'myStoredProc'

DECLARE @strSQL AS VARCHAR(MAX) = 'CREATE TABLE myTableName '

SELECT @strSQL = @strSQL+STUFF((
SELECT ',' +name+' ' + system_type_name 
FROM sys.dm_exec_describe_first_result_set_for_object (OBJECT_ID(@storeProcname),0)
FOR XML PATH('')
),1,1,'(') + ')'

EXEC (@strSQL)

INSERT INTO myTableName
EXEC ('myStoredProc @param1=1, @param2=2')

SELECT * FROM myTableName

DROP TABLE myTableName

Dadurch wird die Definition der zurückgegebenen Tabelle aus den Systemtabellen abgerufen und zum Erstellen der temporären Tabelle verwendet. Sie können es dann aus dem SP wie oben angegeben füllen.

Es gibt auch Varianten davon, die auch mit Dynamic SQL funktionieren.

0
Matthew Baker