SQL Server: SELEZIONA DA stored procedure


334

Ho una procedura memorizzata che restituisce righe:

CREATE PROCEDURE MyProc
AS
BEGIN
    SELECT * FROM MyTable
END

La mia procedura attuale è un po 'più complicata, motivo per cui è necessario uno sproc.

È possibile selezionare l'output chiamando questa procedura?

Qualcosa di simile a:

SELECT * FROM (EXEC MyProc) AS TEMP

Devo usare SELECT TOP X, ROW_NUMBERe una WHEREclausola aggiuntiva per sfogliare i miei dati, e non voglio davvero passare questi valori come parametri.


Non sono sicuro di ciò che intendi fare qui perché quando esegui la procedura, stai recuperando le righe. Vuoi eseguire la procedura all'interno di un'istruzione SELECT in modo da poterla legare a un oggetto paginabile?
Raj More,

1
C'è un motivo particolare per cui non vuoi passare i valori come parametri? Farlo nel modo che stai suggerendo è un po 'inefficace: selezioneresti più dati del necessario e non utilizzeresti tutti.
Mark Bell,

2
Dai un'occhiata qui: sommarskog.se/share_data.html
pylover

Risposte:


149

È possibile utilizzare una funzione definita dall'utente o una vista anziché una procedura.

Una procedura può restituire più set di risultati, ognuno con il proprio schema. Non è adatto per l'uso in una SELECTdichiarazione.


8
Inoltre, se dopo la conversione in un UDF scopri di aver bisogno della semantica della procedura memorizzata, puoi sempre avvolgere l'UDF con una procedura.
Joel Coehoorn,

e se dovessimo inviare i parametri alle procedure memorizzate multiple e combinarle in un'unica grande procedura memorizzata? Può visualizzare, prendere parametri, come fanno le procedure memorizzate
MR

3
@mrN Le visualizzazioni non accettano parametri, ma le UDF lo fanno.
Mehrdad Afshari,

3
Ciao, ho davvero bisogno di farlo senza convertire lo sp in una vista o funzione, è possibile?
Luis Becerril

2
Mentre la tua risposta è una vera affermazione non risponde alla domanda .... "SELEZIONA DA stored procedure" Che sicuramente non è l'ideale, ma è quello che è ... @ La risposta di Aamir è la risposta corretta. O quella o la domanda deve essere cambiata ... il che mi sembra un po 'ridicolo.
Urasquirrel,

202

Puoi

  1. creare una variabile di tabella per contenere il set di risultati dal proc memorizzato e quindi
  2. inserire l'output del proc memorizzato nella variabile table e quindi
  3. usa la variabile table esattamente come faresti con qualsiasi altra tabella ...

... sql ....

Declare @T Table ([column definitions here])
Insert @T Exec storedProcname params 
Select * from @T Where ...

34
Il problema con INSERT #To INSERT @Tè che INSERT EXECun'istruzione non può essere nidificata. Se la procedura memorizzata ne contiene già una INSERT EXEC, questa non funzionerà.
MOHCTP,

2
Questa è probabilmente la soluzione più portatile, essendo la più vicina all'SQL di base. Aiuta anche a mantenere forti definizioni del tipo di colonna. Dovrebbe avere più voti rispetto a quelli sopra.

Qui le variabili della tabella sembrano più utili delle tabelle temporanee in termini di ricompilazione sp. Quindi sono d'accordo, questa risposta dovrebbe avere più voti.
resnyanskiy,

76

Desideri una funzione con valori di tabella o inserire EXEC in una tabella temporanea:

INSERT INTO #tab EXEC MyProc

32
Il problema con INSERT #To INSERT @Tè che INSERT EXECun'istruzione non può essere nidificata. Se la procedura memorizzata ne contiene già una INSERT EXEC, questa non funzionerà.
MOHCTP,

46

Devi leggere OPENROWSET e OPENQUERY

SELECT  * 
INTO    #tmp FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')

4
Come ottenere YOURSERVERNAME in modo dinamico? Non puoi aspettarti di doverlo sapere sempre. Questa pausa non andrà ogni martedì? Quindi se ho 100 server tutti con nomi diversi ...
Urasquirrel,

anche cosa succede se il mio database non è configurato per consentire questo?
Urasquirrel,

4
Prova @@ servername per ottenerlo in modo dinamico
Siddhartha Gandhi il

44

È necessario dichiarare un tipo di tabella che contiene lo stesso numero di colonne restituite dalla procedura del negozio. I tipi di dati delle colonne nel tipo di tabella e le colonne restituite dalle procedure devono essere uguali

declare @MyTableType as table
(
FIRSTCOLUMN int
,.....
)  

Quindi è necessario inserire il risultato della procedura memorizzata nel tipo di tabella appena definito

Insert into @MyTableType 
EXEC [dbo].[MyStoredProcedure]

Alla fine basta selezionare dal tipo di tabella

Select * from @MyTableType

Questa è la soluzione migliore per me, perché non è necessario specificare il nome del server, le stringhe di connessione o non è necessario configurare alcun server collegato per farlo funzionare - che sono cose che non voglio fare solo per ottenere alcuni dati indietro. Grazie! Risposta incredibile!
Matt,

Bella risposta ღ❤ ೋ ღ❤ღ ೋ❤ ღ
Nahid

Quando la stored procedure è troppo difficile - questo metodo non funziona, ad esempio, quando la stored procedure utilizza due tabelle temporanee.
nick_n_a,

34

Non è necessario utilizzare una tabella temporanea.

Questa è la mia soluzione

SELECT  *  FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
WHERE somefield = anyvalue

2
Ciò richiede che tu aggiunga il tuo server come server collegato a se stesso, ma funziona come un incantesimo! Grazie!
vaheeds,

Alcuni grandi avvertimenti su questo: stackoverflow.com/questions/2374741/…
Keith Adler

1
Hmm ... Ricevo l'errore "Errore 7411: il server" YourServerName "non è configurato per DATA ACCESS." Cosa devo cambiare?
Matt,

Hai aggiunto il tuo server come server collegato? YourServerName è il nome del tuo server. Devi cambiare YourServerName con il tuo vero nome del server.
DavideDM,

@Matt:sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;
alexkovelsky,

23

È possibile copiare l'output dalla tabella SP alla tabella temporanea.

CREATE TABLE #GetVersionValues
(
    [Index] int,
    [Name]  sysname,
    Internal_value  int,
    Character_Value sysname
)
INSERT #GetVersionValues EXEC master.dbo.xp_msver 'WindowsVersion'
SELECT * FROM #GetVersionValues
drop TABLE #GetVersionValues

7

usare OPENQUERY e prima di eseguire il set 'SET FMTONLY OFF; SET NOCOUNT ON; '

Prova questo codice di esempio:

SELECT top(1)*
FROM
OPENQUERY( [Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE  [database].[dbo].[storedprocedure]  value,value ')

6

Prova a convertire la procedura in una funzione incorporata che restituisce una tabella come segue:

CREATE FUNCTION MyProc()
RETURNS TABLE AS
RETURN (SELECT * FROM MyTable)

E poi puoi chiamarlo come

SELECT * FROM MyProc()

Hai anche la possibilità di passare parametri alla funzione come segue:

CREATE FUNCTION FuncName (@para1 para1_type, @para2 para2_type , ... ) 

E chiamalo

SELECT * FROM FuncName ( @para1 , @para2 )

6

Se 'DATA ACCESS' falso,

EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE

dopo,

SELECT  *  FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc @parameters')

Funziona.


5

Puoi barare un po 'con OPENROWSET:

SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...

Ciò continuerebbe comunque a eseguire l'intero SP ogni volta, ovviamente.


4

Per semplicità e per renderlo nuovamente eseguibile, ho usato un sistema StoredProcedure "sp_readerrorlog" per ottenere dati:

-----USING Table Variable
DECLARE @tblVar TABLE (
   LogDate DATETIME,
   ProcessInfo NVARCHAR(MAX),
   [Text] NVARCHAR(MAX)
)
INSERT INTO @tblVar Exec sp_readerrorlog
SELECT LogDate as DateOccured, ProcessInfo as pInfo, [Text] as Message FROM @tblVar



-----(OR): Using Temp Table
IF OBJECT_ID('tempdb..#temp') IS NOT NULL  DROP TABLE #temp;
CREATE TABLE #temp (
   LogDate DATETIME,
   ProcessInfo NVARCHAR(55),
   Text NVARCHAR(MAX)
)
INSERT INTO #temp EXEC sp_readerrorlog
SELECT * FROM #temp

1

Sembra che potresti aver solo bisogno di usare una vista . Una vista consente di rappresentare una query come una tabella in modo che possa essere interrogata la vista.


1

Se il tuo server si chiama SERVERX per esempio, è così che l'ho fatto ...

EXEC sp_serveroption 'SERVERX', 'DATA ACCESS', TRUE;
DECLARE @CMD VARCHAR(1000);
DECLARE @StudentID CHAR(10);
SET @StudentID = 'STUDENT01';
SET @CMD = 'SELECT * FROM OPENQUERY([SERVERX], ''SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE MYDATABASE.dbo.MYSTOREDPROC ' + @StudentID + ''') WHERE SOMEFIELD = SOMEVALUE';
EXEC (@CMD);

Per verificare che funzionasse, ho commentato la EXEC()riga di comando e l'ho sostituita conSELECT @CMD per rivedere il comando prima di provare a eseguirlo! Questo per assicurarsi che tutto il numero corretto di virgolette singole fosse nel posto giusto. :-)

Spero che aiuti qualcuno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.