2009-05-01 12 views
27

Ho una stored procedure in SQL Server 2000 che esegue una ricerca in base ai valori dei parametri. Per uno dei parametri passati, ho bisogno di un diverso WHERE clausola seconda del suo valore - il problema è che i 3 valori sarebbero dove MyColumnWHERE IS NULL, NON È NULL o NESSUNA clausola WHERE in base al valore del parametro SQL Server

  1. IS NULL
  2. IS NOT NULL
  3. ANY VALUE (NULL AND NOT NULL) (essenzialmente non WHERE clausola)

Sto avendo un blocco mentale nel venire con la sintassi corretta. È possibile farlo in una istruzione select senza eseguire alcune derivazioni IF @parameter BEGIN ... END?

risposta

38

Ecco come si può risolvere questo utilizzando un unico WHERE clausola:

WHERE (@myParm = value1 AND MyColumn IS NULL) 
OR (@myParm = value2 AND MyColumn IS NOT NULL) 
OR (@myParm = value3) 

Un uso ingenuo della dichiarazione CASE non funziona, con questo voglio dire quanto segue:

SELECT Field1, Field2 FROM MyTable 
WHERE CASE @myParam 
    WHEN value1 THEN MyColumn IS NULL 
    WHEN value2 THEN MyColumn IS NOT NULL 
    WHEN value3 THEN TRUE 
END 

È possibile risolvere questo problema utilizzando una dichiarazione del caso, vedere il giorno answer

+0

Hai avuto la stessa idea di me. Tuttavia, hai bisogno delle parentesi. – BobbyShaftoe

+0

Grazie Bobby, ho aggiornato la mia risposta –

+1

Non sono sicuro che tu faccia o non * abbia * bisogno * delle parentesi, ma sono un grande difensore delle parentesi in espressioni booleane complesse. Non averli lascia il compilatore per fare l'ordine delle operazioni ed è piuttosto spaventoso, se me lo chiedi. –

-1

Si spara d dare un'occhiata alla dichiarazione CASE.

+0

Sì, questo è un altro buon metodo. – BobbyShaftoe

+0

Non credo che tu possa utilizzare l'istruzione CASE in questo scenario poiché CASE valuta l'espressione di un risultato –

+0

Non è così semplice come pensavo fosse in questo caso. È possibile aggiungere un'istruzione case alla clausola select che fa la stessa cosa della clausola WHERE con OR-red ma che ti darebbe solo un'istruzione SQL meno leggibile. Ho aggiornato la mia risposta per mostrarlo. –

12

Si può solo fare qualcosa di simile:

SELECT * 
FROM foo 
WHERE (@param = 0 AND MyColumn IS NULL) 
OR (@param = 1 AND MyColumn IS NOT NULL) 
OR (@param = 2) 

Qualcosa del genere.

+0

Diciamo che devo filtrare con una stringa. Se la stringa è nullo, dovrei restituire tutti i record da una tabella, se non è nullo dovrei restituire tutti i record che corrispondono alla stringa o parte di essa (operatore LIKE). Come lo risolveresti? – Axel

9
WHERE MyColumn = COALESCE(@value,MyColumn) 
  • Se @value è NULL, si confronterà MyColumn a se stesso, ignorando @value = no where clausola.

  • IF @value ha un valore (NOT NULL) si confronterà MyColumn a @value.

Riferimento:COALESCE (Transact-SQL).

+0

Non credo che si possa usare l'istruzione CASE in questo scenario dato che CASE valuta l'espressione di un risultato. COALESCE o anche ISNULL non credo che funzionerà neanche. –

+0

si prega di rivedere la mia modifica, mi manca completamente qualcosa nella tua domanda? –

+0

@Deviant - Penso che manchi leggermente la domanda. La clausola WHERE su MyColumn deve essere impostata da un altro valore perché non si riferisce direttamente al valore del parametro, ad esempio se NULL viene passato, allora la clausola WHERE viene negata. Se viene passato qualsiasi altro valore, il set di risultati sarà solo per WHERE MyColumn equivale a quel valore, non MyColumn con un valore noto. La clausola WHERE di MyColumn con valore NULL non è indirizzata. –

10

Ecco come può essere fatto utilizzando CASE:

DECLARE @myParam INT; 
SET @myParam = 1; 

SELECT * 
    FROM MyTable 
WHERE 'T' = CASE @myParam 
      WHEN 1 THEN 
       CASE WHEN MyColumn IS NULL THEN 'T' END 
      WHEN 2 THEN 
       CASE WHEN MyColumn IS NOT NULL THEN 'T' END 
      WHEN 3 THEN 'T' END; 
5

Un altro modo di CASE:

SELECT * 
FROM MyTable 
WHERE 1 = CASE WHEN @myParm = value1 AND MyColumn IS NULL  THEN 1 
       WHEN @myParm = value2 AND MyColumn IS NOT NULL THEN 1 
       WHEN @myParm = value3       THEN 1 
      END 
+0

+1 soluzione interesstion. :) –

0

Ho avuto successo con questa soluzione. È quasi come quello di Patrick, con una piccola svolta. È possibile utilizzare queste espressioni separatamente o in sequenza. Se il parametro è vuoto, verrà ignorato e tutti i valori relativi alla colonna che verrà visualizzata per la ricerca, inclusi NULLS.

SELECT * FROM MyTable 
WHERE 
    --check to see if @param1 exists, if @param1 is blank, return all 
    --records excluding filters below 
(Col1 LIKE '%' + @param1 + '%' OR @param1 = '') 
AND 
    --where you want to search multiple columns using the same parameter 
    --enclose the first 'OR' expression in braces and enclose the entire 
    --expression 
((Col2 LIKE '%' + @searchString + '%' OR Col3 LIKE '%' + @searchString + '%') OR @searchString = '') 
AND 
    --if your search requires a date you could do the following 
(Cast(DateCol AS DATE) BETWEEN CAST(@dateParam AS Date) AND CAST(GETDATE() AS DATE) OR @dateParam = '')