Funzioni vs stored procedure


88

Diciamo che devo implementare un pezzo di codice T-SQL che deve restituire una tabella come risultato. Posso implementare una funzione con valori di tabella oppure una stored procedure che restituisce un insieme di righe. Cosa dovrei usare?

In breve, quello che voglio sapere è:

Quali sono le principali differenze tra funzioni e stored procedure? Quali considerazioni devo tenere in considerazione per l'utilizzo dell'uno o dell'altro?


1
Questa sembra essere la risposta perfetta: stackoverflow.com/a/1179778/365188
Ozair Kafray

Risposte:


51

Se è probabile che desideri combinare il risultato di questo pezzo di codice con altre tabelle, allora ovviamente una funzione con valori di tabella ti consentirà di comporre i risultati in una singola istruzione SELECT.

In generale, esiste una gerarchia (Visualizza <Funzione TV <Processo memorizzato). Puoi fare di più in ciascuno di essi, ma la capacità di comporre gli output e il coinvolgimento effettivo dell'ottimizzatore diminuisce all'aumentare della funzionalità.

Quindi usa quello che minimamente ti permette di esprimere il risultato desiderato.


50

Le funzioni devono essere deterministiche e non possono essere utilizzate per apportare modifiche al database, mentre le stored procedure consentono di eseguire inserimenti e aggiornamenti, ecc.

È necessario limitare l'uso delle funzioni, poiché rappresentano un enorme problema di scalabilità per query grandi e complesse. Diventano una sorta di "scatola nera" per l'ottimizzatore di query e vedrai enormi differenze nelle prestazioni tra l'utilizzo delle funzioni e il semplice inserimento del codice in una query.

Ma sono sicuramente utili per i rendimenti valutati in tabella in casi molto specifici.

Se è necessario analizzare un elenco delimitato da virgole, per simulare il passaggio di un array a una procedura, una funzione può trasformare l'elenco in una tabella. Questa è una pratica comune con Sql Server 2005, poiché non possiamo ancora passare le tabelle alle stored procedure (possiamo farlo con il 2008).


1
Ma è possibile inviare XML a una stored procedure: stackoverflow.com/questions/144550/...
cllpse

2
Sbagliato, la maggior parte delle funzioni del server SQL non sono deterministiche, come getdate nel server MS-SQL. Solo le funzioni ODBC sono funzioni canoniche (= molto più veloce + indicizzabile) ... Ma hai ragione, si dovrebbe limitare il più possibile l'uso delle funzioni nelle query per motivi di prestazioni.
Stefan Steiger

45

Dai documenti :

Se una stored procedure soddisfa i seguenti criteri, è un buon candidato per essere riscritta come funzione con valori di tabella:

  • La logica è esprimibile in una singola istruzione SELECT ma è una stored procedure, piuttosto che una vista, solo a causa della necessità di parametri.

  • La procedura memorizzata non esegue operazioni di aggiornamento, ad eccezione delle variabili di tabella.

  • Non sono necessarie istruzioni EXECUTE dinamiche.

  • La stored procedure restituisce un set di risultati.

  • Lo scopo principale della stored procedure è creare risultati intermedi che devono essere caricati in una tabella temporanea, che viene quindi interrogata in un'istruzione SELECT.


12

Scriverò alcune differenze interessanti tra stored procedure e funzioni.

  • Possiamo utilizzare le funzioni nelle query di selezione ma non possiamo utilizzare le stored procedure nelle query di selezione.
  • Non possiamo usare funzioni non deterministiche in Functions ma possiamo usare funzioni non deterministiche in stored procedure. Ora sorge la domanda, cos'è la funzione non deterministica .. Ans è: -

    Una funzione non deterministica è quella funzione che restituisce diversi output per gli stessi valori di input in tempi diversi, come getdate (). Restituisce sempre un valore diverso ogni volta che viene eseguito.

    Eccezione:-

    Le versioni precedenti di sql server precedenti a sql 2000 non consentono di utilizzare la funzione getdate () nelle funzioni definite dall'utente, ma la versione 2005 e successive ci consente di utilizzare la funzione getdate () all'interno di una funzione definita dall'utente.

    Newid () è un altro esempio di funzione non deterministica ma non può essere utilizzato nelle funzioni definite dall'utente ma possiamo usarlo nella procedura memorizzata.

  • Possiamo usare istruzioni DML (insert, update, delete) all'interno di una procedura memorizzata ma non possiamo usare istruzioni DML in funzioni su tabelle fisiche o tabelle permanenti. Se vogliamo eseguire operazioni DML nelle funzioni, possiamo farlo su variabili di tabella non su tabelle permanenti.

  • Non è possibile utilizzare la gestione degli errori all'interno della funzione, ma è possibile eseguire la gestione degli errori nelle procedure memorizzate.


Come mai le operazioni DML sono supportate nelle funzioni MySQL?
Joey Pinto

@JoeyPinto. Perché myNONsql non è un reclamo SQL. Certo, ha degli extra, ma non le basi.
PerformanceDBA

8
  1. La procedura può restituire zero o n valori mentre la funzione può restituire un valore obbligatorio.

  2. Le procedure possono avere parametri di input / output mentre le funzioni possono avere solo parametri di input.

  3. La procedura consente l'istruzione select e DML in essa mentre la funzione consente solo l'istruzione select in essa.

  4. Le funzioni possono essere chiamate dalla procedura mentre le procedure non possono essere chiamate dalla funzione.

  5. L'eccezione può essere gestita dal blocco try-catch in una procedura mentre il blocco try-catch non può essere utilizzato in una funzione.

  6. Possiamo andare per la gestione delle transazioni in procedura mentre non possiamo andare in funzione.

  7. Le procedure non possono essere utilizzate in un'istruzione select mentre la funzione può essere incorporata in un'istruzione select.

  8. UDF (funzione definita dall'utente) può essere utilizzata nelle istruzioni SQL in qualsiasi punto della sezione WHERE/ HAVING/ SELECTmentre le procedure memorizzate non possono esserlo.

  9. Le UDF che restituiscono tabelle possono essere trattate come un altro set di righe. Può essere utilizzato in JOINs con altre tabelle.

  10. Le UDF inline possono essere considerate viste che accettano parametri e possono essere utilizzate in se JOINaltre operazioni sui set di righe.


6

Se hai una funzione, potresti usarla come parte della tua istruzione SQL, per esempio

SELECT function_name(field1) FROM table

Non funziona in questo modo per le stored procedure.


1
Penso che stesse parlando di funzioni che restituiscono valori di tabella.
wcm

1
Bene, sto parlando in generale. Ma per il mio caso specifico ora sono attualmente tra una stored procedure o una funzione con valori di tabella.
Auron

5

Ho eseguito alcuni test con un po 'di logica a lunga esecuzione, con lo stesso bit di codice (una lunga istruzione SELECT) in esecuzione sia in una funzione con valore di tabella che in una procedura memorizzata e in un EXEC / SELECT diretto e ciascuno eseguito in modo identico.

A mio parere, utilizza sempre una funzione con valori di tabella anziché una stored procedure per restituire un set di risultati, poiché rende la logica molto più semplice e leggibile nelle query che successivamente si uniscono a esse e consente di riutilizzare la stessa logica. Per evitare un impatto eccessivo sulle prestazioni, utilizzo spesso parametri "opzionali" (ovvero puoi passare loro NULL) per consentire alla funzione di restituire il set di risultati in modo più rapido, ad esempio:

CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int)
AS
RETURN 
    SELECT DISTINCT SiteID, PersonID
    FROM dbo.SiteViewPermissions
    WHERE (@optPersonID IS NULL OR @optPersonID = PersonID)
    AND (@optSiteID IS NULL OR @optSiteID = SiteID)
    AND @RegionID = RegionID

In questo modo puoi utilizzare questa funzione per molte situazioni diverse e non subire un enorme calo delle prestazioni. Credo che questo sia più efficiente del filtraggio in seguito:

SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1

Ho utilizzato questa tecnica in diverse funzioni, a volte con un lungo elenco di parametri "opzionali" di questo tipo.


4

Io personalmente uso le funzioni con valori di tabella quando tutto ciò che restituisco è una singola tabella senza effetti. Fondamentalmente li tratto come viste parametrizzate.

Se ho bisogno di più recordset restituiti o se ci saranno valori aggiornati nelle tabelle, utilizzo una procedura memorizzata.

I miei 2 centesimi


4

Come accennato in precedenza, le funzioni sono più leggibili / componibili / auto documentate, ma sono meno performanti in generale e possono essere seriamente meno performanti se ti lasci trasportare da loro in join come

SELECT *
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2
    ON (tvf1.JoinId = tvf2.JoinId)

Spesso, devi solo accettare la ridondanza del codice che un tvf potrebbe eliminare (a un costo in termini di prestazioni inaccettabile).

Un altro punto che non ho ancora visto menzionato è che non è possibile utilizzare tabelle temporanee che cambiano lo stato del database all'interno di un tvf con più istruzioni. Il meccanismo più funzionalmente equivalente a una tabella temporanea è il cambiamento di stato, nella variabile della tabella di memoria, e per grandi set di dati, una tabella temporanea sarà probabilmente più performante di una variabile di tabella. (Altre alternative includono tabelle dinamiche ed espressioni con valori di tabella comuni, ma a un certo livello di complessità, queste cessano di essere una buona opzione IMO.)


1

Vorrei provarli entrambi. È probabile che l'approccio sp o una tabella derivata sarebbe significativamente più veloce di una funzione e in tal caso dovrebbe essere utilizzato tale approccio. In generale evito le funzioni perché possono essere dei maiali delle prestazioni.


1

Dipende :) Se si desidera utilizzare il risultato con valori di tabella in un'altra procedura, è meglio utilizzare una funzione TableValued. Se i risultati sono per un client, la procedura memorizzata è normalmente la strada migliore da percorrere.


-1

Le stored procedure sono query precompilate che vengono eseguite più velocemente e vengono salvate dalle iniezioni sql. Possono restituire 0 o N valori. Possiamo eseguire operazioni DML all'interno delle stored procedure. Possiamo usare le funzioni all'interno delle procedure e possiamo usare le funzioni nella query di selezione. Le funzioni vengono utilizzate per restituire qualsiasi valore e operazioni DML non possibili nelle funzioni. le funzioni sono di due tipi scalari e tabled-valued. La funzione scalare restituisce un valore singolo, funzione con valori di tabella utilizzata per restituire righe di tabelle.


Questa è una domanda molto vecchia con un gran numero di risposte, molte di esse (compresa la risposta accettata) sono altamente votate. Prima di aggiungere un'altra risposta a un thread del genere dovresti chiederti: "che cosa mancano a tutte quelle risposte esistenti che mi richiedono di scriverne un'altra?"
APC
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.