2009-09-29 19 views
223

Ho una stored procedure che restituisce le righe:SQL Server - selezionare stored procedure

CREATE PROCEDURE MyProc 
AS 
BEGIN 
    SELECT * FROM MyTable 
END 

Il mio procedimento reale è un po 'più complicato, che è il motivo per cui uno sProc è necessario.

È possibile selezionare l'uscita chiamando questa procedura?

Qualcosa di simile:

SELECT * FROM (EXEC MyProc) AS TEMP 

ho bisogno di usare SELECT TOP X, ROW_NUMBER, e un ulteriore WHERE clausola alla pagina i miei dati, e non ho molta voglia di passare questi valori come parametri.

+0

io sono sicuro di ciò che si intende fare qui, perché quando si esegue la procedura, si stanno recuperando le righe. È che si desidera eseguire la procedura all'interno di un'istruzione SELECT in modo da poterla legare a un oggetto paginabile? –

+1

C'è un motivo particolare per cui non si desidera passare i valori come parametri? Per farlo, il modo che stai suggerendo è un po 'inefficiente: selezioneresti più dati del necessario e poi non li utilizzeresti tutti. –

+2

Dai un'occhiata qui: http://www.sommarskog.se/share_data.html – pylover

risposta

105

è possibile utilizzare un User-defined function o un view invece di una procedura.

Una procedura può restituire più set di risultati, ciascuno con il proprio schema. Non è adatto per l'uso in un'istruzione SELECT.

+6

Inoltre, se dopo la conversione in una UDF è necessario disporre della semantica della stored procedure, è sempre possibile avvolgere l'UDF con una procedura. –

+0

E se, abbiamo bisogno di inviare parametri per moltiplicare le stored procedure e combinarle in una grande stored procedure? Può visualizzare, prendere parametri, come le stored procedure fa le viste – mrN

+3

@mrN non prendono parametri, ma le UDF lo fanno. –

62

O si desidera un Table-Valued function o inserire la vostra EXEC in una tabella temporanea:

INSERT INTO #tab EXEC MyProc 
+22

Il problema con 'INSERT # T' o' INSERT @ T' è che un'istruzione 'INSERT EXEC' non può essere annidata. Se la stored procedure ha già un 'INSERT EXEC', non funzionerà. – MOHCTP

117

Puoi

  1. creare una variabile di tabella per contenere il set di risultati dalla stored procedure e poi
  2. inserire l'output del processo memorizzato nella variabile di tabella, e quindi
  3. utilizzare la variabile di tabella esattamente come si farebbe con qualsiasi altra tavolo ...

... sql ....

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

Il problema con 'INSERT # T' o' INSERT @ T' è che un'istruzione 'INSERT EXEC' non può essere annidata. Se la stored procedure ha già un 'INSERT EXEC', non funzionerà. – MOHCTP

+1

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ù uptotes rispetto a quelli sopra. –

+0

Le [variabili tabella] (https://www.simple-talk.com/sql/t-sql-programming/temporary-tables-in-sql-server/) sembrano qui più utili delle tabelle temporanee in termini di ricompilazione dello sp . Quindi sono d'accordo, questa risposta dovrebbe avere più upvotes. – resnyanskiy

2

Sembra che si potrebbe semplicemente essere necessario utilizzare un view . Una vista consente di rappresentare una query come una tabella in modo che possa essere interrogata la vista.

18

È possibile copiare l'output dalla tabella sp a temporaty.

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 
127

Si dovrebbe guardare a questo eccellente articolo di Erland Sommarskog:

Essa elenca praticamente tutte le opzioni disponibili per lo scenario.

+2

Questa dovrebbe essere la risposta accettata. L'articolo di riferimento è molto completo. – ssmith

+1

Grande riferimento, posso vedere me stesso tornare su questo a lungo. –

+0

Ottima risposta, grazie! –

4

Si può imbrogliare un po 'con OPENROWSET:

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

questo sarebbe ancora eseguire l'intera SP ogni volta, naturalmente.

33

è necessario leggere su OPENROWSET e OPENQUERY

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

Non è necessario utilizzare una tabella temporanea.

Questa è la mia soluzione

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

Questo ha bisogno di aggiungere il tuo server come server collegato a se stesso, ma funziona come un incantesimo! Grazie! – vaheeds

+0

Alcuni importanti avvertimenti su questo: http://stackoverflow.com/questions/2374741/why-is-using-openquery-on-a-local-server-bad –

+0

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

2

Prova la conversione del procedimento per una funzione inline che restituisce una tabella come segue:

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

e poi si può chiamare 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 chiamarlo

SELECT * FROM FuncName (@para1 , @para2) 
14

è necessario dichiarare un tipo di tabella che contiene lo stesso numero di colonne vostra procedura negozio sta tornando. tipi di dati delle colonne della tipo di tabella e le colonne restituiti dalle procedure dovrebbero essere lo stesso

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

allora avete bisogno di inserire il risultato della stored procedure nel vostro tipo di tabella appena definito

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

alla fine basta selezionare dal vostro tipo di tabella

Select * from @MyTableType 
+0

Questa è la soluzione migliore per me, perché non è necessario specificare il nome del server, stringhe di connessione o configurare server collegati per farlo funzionare - quali sono le cose che non voglio fare solo per recuperare alcuni dati. Grazie! Bella risposta! – Matt

5

uso OPENQUERY e befor eseguire il set di '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 ') 
0

Se il server si chiama ServerX per esempio, questo è come 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 controllare questo ha funzionato, ho commentato il Riga di comando EXEC() e sostituita con SELECT @CMD per rivedere il comando prima di tentare di eseguirlo! Questo per assicurarsi che tutto il numero corretto di virgolette singole fosse nel posto giusto. :-)

Spero che questo aiuti qualcuno.

2

Se 'ACCESSO DATI' falso,

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

dopo,

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

funziona.

1

Per ragioni di semplicità e di renderla ri-eseguibile, ho usato un sistema StoredProcedure "sp_readerrorlog" per ottenere i 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 
Problemi correlati