T-SQL - funzione con parametri predefiniti


155

Ho questo script:

CREATE FUNCTION dbo.CheckIfSFExists(@param1 INT, @param2 BIT = 1 )
RETURNS BIT
AS
BEGIN
    IF EXISTS ( bla bla bla )
        RETURN 1;
    RETURN 0;
END
GO

Voglio usarlo in una procedura in questo modo:

IF dbo.CheckIfSFExists( 23 ) = 0
    SET @retValue = 'bla bla bla';

Ma ottengo l'errore:

È stato fornito un numero insufficiente di argomenti per la procedura o la funzione dbo.CheckIfSFExists.

Perché non funziona?

Risposte:


227

devi chiamarlo così

SELECT dbo.CheckIfSFExists(23, default)

Da Technet :

Quando un parametro della funzione ha un valore predefinito, la parola chiave DEFAULT deve essere specificata quando viene chiamata la funzione per recuperare il valore predefinito. Questo comportamento è diverso dall'uso di parametri con valori predefiniti nelle stored procedure in cui l'omissione del parametro implica anche il valore predefinito. Un'eccezione a questo comportamento è quando si richiama una funzione scalare usando l'istruzione EXECUTE. Quando si utilizza EXECUTE, la parola chiave DEFAULT non è richiesta.


80
Vedendo questo sono frustrato. Non sto sfruttando l' defaultidea qui ... Devo andare a cambiare tutti i posti adesso.
LCJ,

8
@Lijo, ottieni comunque il vantaggio di non duplicare il tuo valore predefinito concreto ad ogni chiamata.
Frédéric,

9
Poiché non ci è consentito sovrapporre e il "valore predefinito" ha quindi un'usabilità limitata, spesso l'approccio migliore sarà quello di creare una nuova versione estesa con un suffisso (ad esempio CheckIfSFExistsEX qui) con i parametri extra e cambiare la funzione originale in solo chiamando la versione estesa con il parametro "default". In questo modo TUTTO il codice esistente funziona e hai solo un posto da mantenere.
Eske Rahn,

39

Puoi chiamarlo in tre modi: con parametri, con DEFAULT e tramite EXECUTE

SET NOCOUNT ON;

DECLARE
@Table  SYSNAME = 'YourTable',
@Schema SYSNAME = 'dbo',
@Rows   INT;

SELECT dbo.TableRowCount( @Table, @Schema )

SELECT dbo.TableRowCount( @Table, DEFAULT )

EXECUTE @Rows = dbo.TableRowCount @Table

SELECT @Rows

11
Perché la DEFAULTparola chiave è richiesta in select, ma può essere omessa in esecuzione? Questo fa schifo: / Speriamo che un giorno venga risolto.
Misiu,

@Misiu, non è qualcosa che deve essere "riparato". Questo è di progettazione. Ho letto molte alternative per avvicinarmi a un obiettivo "ideale" di poter semplicemente chiamare una funzione senza specificare ogni argomento, ma non ho visto una spiegazione chiara del perché ciò sia necessario. Il codice dovrebbe essere chiaro e una strategia per raggiungere ciò richiede che il programmatore sia sempre consapevole del fatto che "hey, stai chiamando una funzione che ha questo e questi altri argomenti, che hanno valori predefiniti. Non dimenticare che il i valori predefiniti POSSONO ESSERE MODIFICATI ". Quindi, IMO, questa è una buona "cosa cattiva" da avere.
Gustavo Pinsard,

16

Con le funzioni definite dall'utente, devi dichiarare ogni parametro, anche se hanno un valore predefinito.

Quanto segue verrebbe eseguito correttamente:

IF dbo.CheckIfSFExists( 23, default ) = 0
    SET @retValue = 'bla bla bla;

-1

Un modo per aggirare questo problema è utilizzare le stored procedure con un parametro di output.

exec sp_mysprocname @returnvalue output, @firstparam = 1, @ secondparam = 2

valori che non vengono passati per impostazione predefinita ai valori predefiniti impostati nella stessa procedura memorizzata. E puoi ottenere i risultati dalla tua variabile di output.


1
La modifica della funzione in una procedura memorizzata non è in genere una buona soluzione, poiché una procedura memorizzata non può essere richiamata da una query, ma una funzione può farlo.
Lama

È vero, tuttavia non tutti i blocchi di codice devono essere richiamati all'interno di una query. È stato dimostrato che sql non ha un buon metodo di gestione dei valori predefiniti per le funzioni (l'uso della parola chiave predefinita è quasi tanto quanto l'aggiunta di un valore). Non è una buona soluzione generale, ma funziona benissimo in alcuni casi d'uso.
Jereme Guenther,

Le persone continuano a segnare questo, tuttavia mi attengo. Se è necessario disporre di un blocco di codice riutilizzabile, che non verrà chiamato all'interno delle query e si desidera la flessibilità di veri parametri opzionali con valori predefiniti, una procedura memorizzata è comunque migliore di una funzione.
Jereme Guenther,

1
L'uso di stored procedure non significa utilizzarle anziché utilizzare una funzione, ma può significare utilizzare la stored procedure come wrapper attorno a una funzione. Uso spesso questa tecnica; le parole chiave predefinite sono ora nascoste all'interno del proc. Penso che questa idea vada bene. Mi permette anche di rendere predefinite più complicate, se lo desidero, separato dalla funzione, che può essere lasciata in uno stato più puro.
J Bryan Price
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.