Opérateurs logiques OU ET en condition et ordre des conditions dans WHERE

33

Examinons ces deux déclarations:

IF (CONDITION 1) OR (CONDITION 2)
...

IF (CONDITION 3) AND (CONDITION 4)
...

Si CONDITION 1est TRUE, sera CONDITION 2vérifié?
Si CONDITION 3est FALSE, sera CONDITION 4vérifié?

Qu'en est-il des conditions sur WHERE: le moteur SQL Server optimise-t-il toutes les conditions d'une WHEREclause? Les programmeurs doivent-ils placer les conditions dans le bon ordre pour s'assurer que l'optimiseur SQL Server les résout correctement ?

AJOUTÉE:

Merci à Jack pour le lien, surprise de t-sql code:

IF  1/0 = 1 OR 1 = 1
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result


IF  1/0 = 1 AND 1 = 0
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result

Il n'y a pas d' exception de division par zéro dans ce cas.

CONCLUSION:

Si C ++ / C # / VB est court-circuité, pourquoi SQL Server ne l’a-t-il pas?

Pour répondre réellement à cette question, examinons comment les deux fonctionnent avec des conditions. C ++ / C # / VB ont tous un court-circuit défini dans les spécifications du langage pour accélérer l'exécution du code. Pourquoi s'embêter à évaluer les conditions N OR lorsque la première est déjà vraie ou les conditions M AND lorsque la première est déjà fausse.

En tant que développeurs, nous devons savoir que SQL Server fonctionne différemment. C'est un système basé sur les coûts. Pour obtenir le plan d’exécution optimal pour notre requête, le processeur de requête doit évaluer chaque condition sur chaque et lui attribuer un coût. Ces coûts sont ensuite évalués dans leur ensemble pour former un seuil qui doit être inférieur au seuil défini par SQL Server pour un bon plan. Si le coût est inférieur au seuil défini, le plan est utilisé, sinon le processus complet est répété avec une combinaison différente de coûts de condition. Le coût ici est soit une analyse, soit une jointure de fusion ou de fusion, ou une jointure de hachage, etc. Pour cette raison, le court-circuitage tel qu’il est disponible en C ++ / C # / VB n’est tout simplement pas possible. Vous pourriez penser que forcer l'utilisation de l'index sur une colonne est considéré comme un court-circuit, mais ce n'est pas le cas. Cela force seulement l'utilisation de cet index et avec cela raccourcit la liste des plans d'exécution possibles. Le système est toujours basé sur les coûts.

En tant que développeur, vous devez savoir que SQL Server ne court-circuite pas comme dans les autres langages de programmation et vous ne pouvez rien y faire.

garik
la source
D'où vient le dernier bloc de devis? Pourriez-vous ajouter une référence?
Nick Chammas

Réponses:

25

SQL Server ne garantit pas si ni dans quel ordre les instructions seront traitées dans une WHEREclause. La seule expression qui permet de court-circuiter une instruction est CASE- WHEN. Ce qui suit est issu d'une réponse que j'ai postée sur Stackoverflow:

Comment SQL Server court-circuite l'évaluation des conditions WHERE

Cela se produit quand on en a envie, mais pas comme on le pense tout de suite.

En tant que développeur, vous devez savoir que SQL Server ne court-circuite pas comme dans les autres langages de programmation et vous ne pouvez rien y faire .

Pour plus de détails, consultez le premier lien dans l'entrée de blog ci-dessus, qui mène à un autre blog:

Est-ce que SQL Server court-circuite?

Le verdict final? Eh bien, je n'en ai pas encore vraiment, mais il est probablement prudent de dire que le seul moment où vous pouvez assurer un court-circuit spécifique est lorsque vous exprimez plusieurs conditions WHEN dans une expression CASE. Avec les expressions booléennes standard, l'optimiseur déplacera les choses comme bon lui semble en fonction des tables, des index et des données que vous interrogez.

MicSim
la source
2
Apparemment, il y a des cas extrêmes (ou un bug) où même case n'est pas sûr
Jack Douglas
1
Je démontre également un autre cas (ha!) Où les CASEpauses: dba.stackexchange.com/questions/12941/…
Aaron Bertrand
0

SQL est un langage de programmation déclaratif . Contrairement au C ++, par exemple, qui est un langage de programmation impératif .

Vous pouvez dire ce que vous voulez dans le résultat final, mais vous ne pouvez pas dicter comment le résultat est exécuté, tout dépend du moteur.

Le seul véritable moyen de garantir le "court-circuit" (ou tout autre flux de contrôle ) à l'intérieur WHEREest d'utiliser des vues indexées, des tables temporaires et des mécanismes similaires.

PS Vous pouvez également utiliser des astuces de plan d'exécution (pour indiquer au moteur comment exécuter une requête, quels index utiliser et COMMENT les utiliser), je pensais juste que je devrais le mentionner, alors que nous en sommes à ce sujet ...

jitbit
la source
-4

1) - OU (n'importe laquelle ou les deux conditions seront VRAIES)

Si la condition 1 est VRAIE, la condition 2 sera également vérifiée. Elle peut être VRAI ou FAUX.

--AND (les deux conditions doivent être VRAIES)

si la condition 1 est FAUX, la condition 2 ne sera pas vérifiée

Ranjith Kumar
la source
"Si la condition 1 est FALSE, la condition 2 ne sera pas vérifiée" Ce n'est pas vrai. Voir la réponse ci-dessus . SQL Server peut encore évaluer la condition 2 car il n'effectue pas d'évaluation de court-circuit dans les WHEREclauses.
Nick Chammas
-4

Le seul moyen de contrôler la manière dont les conditions de la clause WHERE est consiste à utiliser des crochets pour les regrouper.

WHERE Col1 = 'Something' AND Col2 = 'Something' OR Col3 = 'Something' and Col4 = 'Something'

est très différent de

WHERE (Col1 = 'Something' AND Col2 = 'Something') OR (Col3 = 'Something' and Col4 = 'Something')
mrdenny
la source
Juste curieux. Comment ces deux conditions sont-elles différentes? Différents résultats, performances, plan d'exécution? Je pensais qu'ils seraient équivalents.
Ypercubeᵀᴹ
Avec le premier, vous devez faire correspondre Col1, Col4 et Col2 ou Col3. Dans la deuxième ligne, pour correspondre à Col1 et Col2 ou vous devez associer Col3 et Col4, mais Col1 et Col4 n'auront jamais besoin d'être évalués ensemble.
mrdenny
1
Non tu as tort. ANDa une priorité plus élevée que OR. Les deux sont équivalents. Ce que vous dites serait vrai pour la WHERE Col1 = x AND (Col2 = x OR Col3 = x) AND Col4 = xrequête. Voir le test SQL-Fiddle
ypercubeᵀᴹ