Domanda

Ho lavorato sull'ottimizzazione di una query e mi sono imbattuto in una situazione che mi ha fatto dubitare di come ho sempre usato l'operatore OR di SQL. (Anche SQL Server 2000)

Ho una query in cui la clausola condizionale (WHERE) assomiglia a questa:

WHERE (Column1 = @Param1 or Column1 LIKE @Param1 + '%')
AND (@Param2 = '' OR Column2 = @Param2 OR Column2 LIKE @Param2 + '%')

Ora, ho sempre capito che OR in SQL ha valutato entrambe le espressioni. Quindi tutti i record valutati true per l'espressione a sinistra verranno restituiti insieme a tutti i record valutati true sull'espressione giusta. Ad esempio:

SELECT * FROM TABLE1
WHERE COL1 = 'Test' OR Col2 = 'Data'

Ciò restituirebbe tutti i record in cui COL1 è "Test", nonché qualsiasi record in cui Col2 è "Dati"

Nell'esempio sopra, ho modificato Column2 in base a quanto segue:

AND(Column2 LIKE ISNULL(@Param2, '') + '%')

All'improvviso ottengo 0 righe restituite.

Sono stato confuso nel fatto che OR valuta solo le espressioni fino a quando non trova un risultato VERO o c'è una condizione che potrebbe far sì che i 2 diversi restituiscano risultati diversi?

È stato utile?

Soluzione

" OR valuta solo le espressioni fino a quando non trova un VERO risultato "

Deve solo farlo, ma non è questo il tuo problema (in realtà questo è ciò che ti ha salvato nel tuo caso originale). Le tue due query non sono realmente equivalenti.

Penso che tu abbia NULL in Column2 che non causerà mai (Column2 LIKE ISNULL (@ Param2, '') + '%') per essere vero - e nella tua versione originale il @ Param2 = '' stava mascherando questo caso, poiché è vero (a volte)

Forse:

(ISNULL(Column2, '') LIKE ISNULL(@Param2, '') + '%')

Ricorda la logica a tre valori per i NULL:

TRUE and UNKNOWN: UNKNOWN
TRUE or UNKNOWN: TRUE

FALSE and UNKNOWN: FALSE
FALSE or UNKNOWN: UNKNOWN

Ma non sono sicuro che la tua ottimizzazione stia davvero aiutando.

Altri suggerimenti

OR non è onnicomprensivo, soprattutto perché è tra parentesi. Quello che hai in una versione più grande è: DOVE X AND Y . Il fatto che X e Y siano esse stesse espressioni booleane che fanno uso di un OR non è importante: vengono valutati separatamente e quindi i risultati vengono inviati all'operatore AND.

[modifica]:
Rileggendo, potrei aver frainteso la tua domanda. Con questo in mente, dovrò andare con l'altra risposta, perché NULL LIKE '%' restituisce NULL, che è lo stesso di falso in questo caso. Puoi provare questo invece:

COALESCE(Column2,'') LIKE COALESCE(@param2,'') + '%'

Cordiali saluti, ci sono esperimenti molto semplici che puoi fare per vedere che non tutte le condizioni sono necessariamente valutate.

L'ho fatto in Oracle ma mi aspetto che tu abbia un risultato simile in SQL Server.

dev> select * from dual where 1=1 or 1/0 = 3;

D
-
X

La condizione dopo l'OR non deve essere stata valutata, poiché genererebbe un errore di divisione per zero.

Questa gestione di operatori booleani è generalmente nota come "corto circuito". e, AFAIK, è piuttosto standard nelle lingue moderne. Può anche applicarsi in un'espressione AND - se la prima condizione è falsa, non ha senso valutare la seconda condizione, poiché l'intera espressione non può essere TRUE.

Ulteriori informazioni: http://en.wikipedia.org/wiki/Short-circuit_evaluation

Comunque, come ha detto Cade, il tuo vero problema è probabilmente la gestione errata dei NULL.

MS-SQL valuterà prima il lato sinistro e non procederà a meno che non sia necessario.

Questo è lo stesso con il connettore AND, il lato sinistro verrà valutato e se falso il diritto non verrà evocato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top