Le court-circuit de la clause SQL WHERE est-il évalué?

Par exemple:

SELECT * FROM Table t WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key) 

Si @key IS NULL est évalué à true, @key est PAS NULL ET @key = t.Key évalué?

Si non, pourquoi pas?

Si oui, est-ce garanti? Cela fait-il partie d’ANSI SQL ou est-il spécifique à la firebase database?

Si firebase database spécifique, SqlServer? Oracle? MySQL?

Référence: évaluation de court-circuit

ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf

6.3.3.3 Ordre d’évaluation des règles

[…]

Lorsque la priorité n’est pas déterminée par les formats ou entre parenthèses, l’évaluation effective des expressions est généralement effectuée de gauche à droite. Toutefois, il dépend de l’ implémentation si les expressions sont réellement évaluées de gauche à droite, en particulier lorsque les opérandes ou les opérateurs peuvent provoquer des conditions ou si les résultats des expressions peuvent être déterminés sans évaluer complètement toutes les parties de l’expression.

De ce qui précède, le court-circuit n’est pas vraiment disponible.

Si vous en avez besoin, je suggère une déclaration de cas:

 Where Case when Expr1 then Expr2 else Expr3 end = desiredResult 

Expr1 est toujours évalué, mais un seul parmi Expr2 et Expr3 sera évalué par ligne.

Je pense que c’est l’un des cas où je l’écrirais comme s’il ne court-circuitait pas, pour trois raisons.

  1. Parce que pour MSSQL, ce n’est pas résolu en regardant BOL à la place évidente, donc pour moi, cela le rend canoniquement ambigu.

  2. car au moins je sais que mon code fonctionnera. Et plus important encore, ceux qui viendront après moi, alors je ne les mets pas sous le coup de la même question encore et encore.

  3. J’écris assez souvent pour plusieurs produits de SGBD et je ne veux pas avoir à me souvenir des différences si je peux les contourner facilement.

Je ne crois pas que le court-circuit dans SQL Server (2005) soit garanti. SQL Server exécute votre requête via son algorithme d’optimisation qui prend en compte un grand nombre d’éléments (index, statistiques, taille de tableau, ressources, etc.) pour élaborer un plan d’exécution efficace. Après cette évaluation, vous ne pouvez pas dire avec certitude que votre logique de court-circuit est garantie.

J’ai moi-même rencontré la même question il y a quelque temps et mes recherches ne m’ont vraiment pas donné de réponse définitive. Vous pouvez écrire une petite requête pour vous donner une idée du fonctionnement, mais pouvez-vous être sûr que la charge de votre firebase database augmente, que les tables deviennent plus grandes et que les choses sont optimisées et modifiées dans la firebase database? tenir. Je n’ai donc pas pu et par conséquent j’ai fait preuve de prudence et j’ai utilisé CASE dans la clause WHERE pour assurer un court-circuit.

Vous devez garder à l’esprit le fonctionnement des bases de données. Étant donné une requête paramétrée, la firebase database crée un plan d’exécution basé sur cette requête sans les valeurs des parameters. Cette requête est utilisée à chaque exécution de la requête, quelles que soient les valeurs fournies. Que les courts-circuits de requête avec certaines valeurs importent peu dans le plan d’exécution.

Je l’utilise généralement pour les parameters facultatifs. Est-ce la même chose qu’un court-circuit?

 SELECT [blah] FROM Emp WHERE ((@EmpID = -1) OR (@EmpID = EmpID)) 

Cela me donne la possibilité de passer -1 ou autre pour tenir compte de la vérification facultative d’un atsortingbut. Parfois, cela implique de rejoindre plusieurs tables, ou de préférence une vue.

Très pratique, pas tout à fait sûr du travail supplémentaire qu’il donne au moteur de firebase database.

Pour SQL Server, je pense que cela dépend de la version, mais mon expérience avec SQL Server 2000 est qu’il évalue toujours @key = t.Key même lorsque @key est nul. En d’autres termes, il ne fait pas de court-circuit efficace lors de l’évaluation de la clause WHERE.

J’ai vu des gens recommander une structure comme votre exemple pour faire une requête flexible où l’utilisateur peut entrer ou ne pas entrer divers critères. Mon observation est que Key est toujours impliqué dans le plan de requête lorsque @key est null et que si Key est indexé, il n’utilise pas efficacement l’index.

Ce type de requête flexible avec différents critères est probablement un cas où le SQL créé dynamicment est vraiment la meilleure solution. Si @key est nul, vous ne l’incluez simplement pas dans la requête.

Je ne sais pas à propos de court circulant, mais je l’écrirais comme une déclaration si-sinon

 if (@key is null) begin SELECT * FROM Table t end else begin SELECT * FROM Table t WHERE t.Key=@key end 

De plus, les variables doivent toujours figurer à droite de l’équation. Cela le rend sargable.

http://en.wikipedia.org/wiki/Sargable

Juste trébuché sur cette question, et avait déjà trouvé cette entrée de blog: http://rusanu.com/2009/09/13/on-sql-server-boolean-operator-short-circuit/

Le serveur SQL est libre d’optimiser une requête où bon lui semble, de sorte que dans l’exemple donné dans le billet de blog, vous ne pouvez pas vous fier au court-circuit.

Cependant, un CASE est apparemment documenté pour être évalué dans l’ordre écrit – vérifiez les commentaires de cet article.

La principale caractéristique de l’évaluation de court-circuit est qu’il arrête l’évaluation de l’expression dès que le résultat peut être déterminé. Cela signifie que le rest de l’expression peut être ignoré, car le résultat sera le même peu importe qu’il soit évalué ou non.

Les opérateurs booléens binarys sont comutatifs, ce qui signifie:

 a AND b == b AND a a OR b == b OR a a XOR b == b XOR a 

il n’y a donc aucune garantie sur l’ordre d’évaluation. L’ordre d’évaluation sera déterminé par l’optimiseur de requête.

Dans les langages contenant des objects, il peut y avoir des situations où vous pouvez écrire des expressions booléennes qui ne peuvent être évaluées qu’avec une évaluation de court-circuit. Votre exemple de construction de code est souvent utilisé dans ces langages (C #, Delphi, VB). Par exemple:

 if(someSsortingng == null | someSsortingng.Length == 0 ) printf("no text in someSsortingng"); 

Cet exemple C # provoquera une exception si someSsortingng == null car il sera entièrement évalué. En évaluation de court-circuit, il fonctionnera à chaque fois.

SQL ne fonctionne que sur des variables scalaires (aucun object) qui ne peuvent pas être non initialisées. Il est donc impossible d’écrire des expressions booléennes qui ne peuvent pas être évaluées. Si vous avez une valeur NULL, toute comparaison renverra false.

Cela signifie qu’en SQL, vous ne pouvez pas écrire une expression qui est évaluée différemment en fonction de l’utilisation d’un court-circuit ou d’une évaluation complète.

Si l’implémentation SQL utilise l’évaluation des courts-circuits, elle ne peut que accélérer l’exécution des requêtes.

Ci-dessous un test rapide et sale sur SQL Server 2008 R2:

 SELECT * FROM table WHERE 1=0 AND (function call to complex operation) 

Cela retourne immédiatement sans enregistrement. Type de comportement de court-circuit était présent.

Alors essayé ceci:

 SELECT * FROM table WHERE (a field from table) < 0 AND (function call to complex operation) 

sachant qu'aucun enregistrement ne satisferait à cette condition:

 (a field from table) < 0 

Cela a pris plusieurs secondes, indiquant que le comportement de court-circuit n'était plus là et que l'opération complexe était en cours d'évaluation pour chaque enregistrement.

J'espère que cela aide les gars.

Voici une démo pour prouver que MySQL exécute un court-circuit de clause WHERE :

http://rextester.com/GVE4880

Cela exécute les requêtes suivantes:

 SELECT myint FROM mytable WHERE myint >= 3 OR myslowfunction('query #1', myint) = 1; SELECT myint FROM mytable WHERE myslowfunction('query #2', myint) = 1 OR myint >= 3; 

La seule différence entre ceux-ci est l’ordre des opérandes dans la condition OU.

myslowfunction dort délibérément une seconde et a pour effet secondaire d’append une entrée à une table de journalisation à chaque exécution. Voici les résultats de ce qui est enregistré lors de l’exécution des deux requêtes ci-dessus:

 myslowfunction called for query #1 with value 1 myslowfunction called for query #1 with value 2 myslowfunction called for query #2 with value 1 myslowfunction called for query #2 with value 2 myslowfunction called for query #2 with value 3 myslowfunction called for query #2 with value 4 

Ce qui précède montre qu’une fonction lente est exécutée plusieurs fois lorsqu’elle apparaît sur le côté gauche d’une condition OU lorsque l’autre opérande n’est pas toujours vrai (en raison d’un court-circuit).

Cela prend 4 secondes supplémentaires dans l’parsingur de requêtes, donc d’après ce que je peux voir, IF n’est même pas court-circuité …

 SET @ADate = NULL IF (@ADate IS NOT NULL) BEGIN INSERT INTO #ABla VALUES (1) (SELECT bla from a huge view) END 

Ce serait bien d’avoir un chemin garanti!

Il est évident que le serveur MS Sql prend en charge la théorie des courts-circuits pour améliorer les performances en évitant les vérifications inutiles.

Exemple à l’appui:

 SELECT 'TEST' WHERE 1 = 'A' SELECT 'TEST' WHERE 1 = 1 OR 1 = 'A' 

Ici, le premier exemple entraînerait une erreur “La conversion a échoué lors de la conversion de la valeur varchar ‘A’ en type de données int. ‘

Alors que la seconde s’exécute facilement, la condition 1 = 1 est évaluée à TRUE et la deuxième condition ne s’exécute pas du tout.

En outre

 SELECT 'TEST' WHERE 1 = 0 OR 1 = 'A' 

ici, la première condition serait évaluée à false et le SGBD irait donc à la deuxième condition et vous obtiendrez à nouveau l’erreur de conversion comme dans l’exemple ci-dessus.

REMARQUE: Je me suis désintéressé de la situation juste pour réaliser les conditions météorologiques. L’état est exécuté ou court-circuité si les résultats de la requête présentent une erreur, c’est-à-dire la condition exécutée, sauf les circulations courtes.

EXPLICATION SIMPLE

Considérer,

 WHERE 1 = 1 OR 2 = 2 

comme la première condition est évaluée à TRUE , il est inutile d’évaluer la deuxième condition car son évaluation, quelle que soit la valeur, n’affecte pas du tout le résultat, donc Sql Server a la possibilité d’économiser le temps d’exécution des requêtes .

dans le cas de “OU” si la première condition est évaluée à VRAI, la chaîne entière connectée par “OU” serait considérée comme évaluée à vraie sans évaluer les autres.

 condition1 OR condition2 OR ..... OR conditionN 

Si la condition1 est évaluée à true, faites reposer toutes les conditions jusqu’à ce que conditionN soit ignoré. Dans les mots généralisés à la détermination de la première valeur TRUE , toutes les autres conditions liées par OU seraient ignorées.

Considérons la deuxième condition

 WHERE 1 = 0 AND 1 = 1 

comme la première condition est évaluée à FALSE, elle n’a pas de sens pour évaluer la seconde condition, car son évaluation en n’importe quelle valeur n’affecterait pas du tout le résultat, donc encore une bonne opportunité pour Sql Server de sauver le temps d’exécution des requêtes .

dans le cas de “AND”, si la première condition est évaluée à FALSE, la chaîne entière connectée au “AND” serait considérée comme évaluée à FALSE sans évaluer les autres.

 condition1 AND condition2 AND ..... conditionN 

Si la condition1 est évaluée à FALSE , place toutes les conditions jusqu’à ce que conditionN soit ignorée. Dans les mots généralisés à la détermination du premier FALSE , toutes les autres conditions liées par AND seraient ignorées.

AINSI, UN PROGRAMMATEUR WISE DEVRAIT TOUJOURS PROGRAMMER LA CHAINE DE CONDITIONS DE MANIERE A EVALUER EN PREMIER MOINS DES CONDITIONS SANS DIMINUTION OU PLUS ÉLIMINATOIRES, OU À DISPOSER CETTE CONDITION DE MANIERE A PROFITER MAXIMUM DU COURT CIRCUIT