2012-04-17 16 views
23

Supponiamo che ci sia una procedura memorizzata con 3 parametri. Fuori di tutte le possibilità, sto cercando di raggiungere questo obiettivo con una sola clausola di WHERE senza ottenere fuori controllo con l'utilizzo di () AND() OR() troppo ...Argomenti opzionali nella clausola WHERE

Esempio:

//Params 
@CITY VARCHAR(100) = NULL, 
@GENDER VARCHAR(100) = NULL, 
@AGE VARCHAR(100) = NULL 

Suppongo che si può fare usando IF BEGIN ... END per ogni variabile se esiste, ma questo rende il codice molto più lungo di quanto desiderato ..

Questo metodo non funzionerà perché è troppo lungo (ci sono circa 10 campi diversi come questo, ma l'esempio è solo 3.) e non sono sicuro se persino tira direttamente su valori distintivi ...

SELECT NAME FROM TABLE 
WHERE (
([email protected] AND [email protected] AND [email protected]) 
OR ([email protected] AND [email protected]) 
OR ([email protected] AND [email protected]) 
OR ([email protected] AND [email protected]) 
OR ([email protected]) 
OR ([email protected]) 
OR ([email protected]) 
) 

Esiste un modo ancora più breve ed efficiente per farlo?

Se sì, è preferibile che il metodo sia compatibile anche con JOIN.

+1

Side-nota: quando si definisce un 'VARCHAR()' - come parametro per un proc memorizzato o una variabile locale - dovrebbe ** sempre ** avere una ** lunghezza ** definita! Altrimenti potresti finire inavvertitamente con 'VARCHAR (1)' stringhe '... –

+0

I campi facoltativi significano se non esiste il valore o' NULL', quindi non mostrarlo nella clausola Where, è possibile? –

+2

Leggi questo: [Condizioni di ricerca dinamica in T-SQL] (http://sommarskog.se/dyn-search-2008.html) –

risposta

41

alternativa ai ISNULL/COALESCE opzioni, è possibile verificare i parametri per essere nullo:

SELECT NAME 
FROM TABLE 
WHERE 
    (@City IS NULL OR City = @City) 
AND 
    (@Gender IS NULL OR Gender = @Gender) 
AND 
    (@Age IS NULL OR Age = @Age) 
+4

So che è un po 'troppo tardi per un commento, ma per favore sii prudente con questo approccio dato che SQL Server non garantisce l'ordine della valutazione (non farà sicuramente il cortocircuito). Quindi potresti anche finire SQL Server facendo tutti i controlli non necessari. –

+1

@IlyaChernomordik: E prestazioni di scarico in discesa. – Neolisk

+0

@IlyaChernomordik quindi quale sarebbe un modo migliore per farlo? Pensato di SQL dinamico ma porta altri problemi come la manutenzione, la verifica del codice, ecc. Non c'è altro modo migliore? –

0

Possibilmente questo:

create procedure myProc 
    --Params 
@CITY VARCHAR(100) = NULL, 
@GENDER VARCHAR(100) = NULL, 
@AGE VARCHAR(100) = NULL 
as 

SELECT NAME FROM [TABLE] 
WHERE ISNULL(CITY,'')=ISNULL(@CITY,ISNULL(CITY,'')) 
AND ISNULL(GENDER,'')=ISNULL(@GENDER,ISNULL(GENDER,'')) 
AND ISNULL(AGE,'')=ISNULL(@AGE,ISNULL(AGE,'')) 
go 

Supponendo che le colonne nella clausola WHERE sono annullabile, utilizzando ISNULL per evitare confronto nullo.

+0

uggghhh .. volevo evitare di farlo in questo modo .. qualcosa come "IsNull"? –

+0

Potresti provare questa opzione –

4

provare qualcosa di simile:

SELECT NAME 
FROM TABLE 
WHERE 
    City = IsNull(@City, City) AND 
    Gender = IsNull(@Gender, Gender) AND 
    Age = IsNull(@Age, Age) 

O:

SELECT NAME 
FROM TABLE 
WHERE 
    (City = @City OR @City IS NULL) AND 
    (Gender = @Gender OR @Gender IS NULL) AND 
    (Age = @Age OR @Age IS NULL) 
+0

penso che il tuo primo esempio possa tagliarlo, fammi controllare .. brb. –

+0

Per quanto riguarda la prima opzione .... NULL è uguale a NULL? –

+0

'Selezionare * Dalla tabella in cui NULL IS NULL restituirà tutte le righe. Va bene in questo contesto perché significa che non si vuole filtrare l'argomento se si passa un valore 'NULL'. – Greg

10

che dire di questo?

SELECT 
    NAME 
FROM TABLE 
WHERE CITY = COALESCE(@CITY, CITY) 
    AND GENDER = COALESCE(@GENDER, GENDER) 
    AND AGE = COALESCE(@AGE, AGE) 
+1

Bello! Si spera che SQL Server sia in grado di ottimizzare le condizioni in caso di rilevamento di variabili nulle. Sarebbe interessante da testare. – l33t

1
SELECT NAME 
FROM TABLE 
WHERE  
    City = case when isnull(@City ,'') = '' then City 
         else @City end 
AND  
    Gender = case when isnull(@Gender ,'') = '' then Gender 
         else @Gender end 
AND 
    Age = case when isnull(@Age ,0) = 0 then Age 
         else @Age end  
+0

Dubito che la condizione City = City e in generale Column = Column Condition sia una condizione inefficace, ad esempio null = null potrebbe portarci a UNKNOWN e d'altra parte se la nostra colonna sarebbe Not null, finiremo con una tabella di scansione completa per la condizione column = column. – siamak