2010-09-14 21 views
5

necesito para consultar los datos de una segunda tabla, pero sólo si se cumple una serie rara de las condiciones de la tabla principal:¿Tiene MySQL Short Circuit la función IF()?

SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM tablea ... 

a, b, y las condiciones C son casi siempre falsa, por lo que mi pensamiento es la subconsulta nunca se ejecutará para la mayoría de las filas en el conjunto de resultados y, por lo tanto, será mucho más rápida que una combinación. Pero eso solo sería cierto si la declaración IF() cortocircuita.

¿Lo tiene?

Gracias por cualquier ayuda que ustedes puedan proporcionar.

Respuesta

2

Con la ayuda de J. Jorgenson me ocurrió con mi propio caso de prueba. Su ejemplo no intenta hacer un cortocircuito en la evaluación de la condición, pero al usar su idea, hice mi propia prueba y verifiqué que MySQL realmente cortocircuita la verificación de la condición IF().

SET @var:=5; 
SELECT IF(1 = 0 AND (@var:=10), 123, @var); #Expected output: 5 
SELECT IF(1 = 1 AND (@var:=10), @var, 123); #Expected output: 10 

En el segundo ejemplo, MySQL es propiamente un cortocircuito: @var nunca se establece en 10.

Gracias por la ayuda J. Jorgenson!

0

Pruébelo en el analizador SQL. Si desea estar seguro y no tener que confiar en que la base de datos funcione de una manera (y no cambiar ese comportamiento en versiones nuevas), solo haga dos consultas y realice el IF de forma programática.

8

La respuesta es SÍ.
El IF (cond, expr_true, expr_false) dentro de una consulta mysql está cortocircuitado.

Aquí una prueba, utilizando @variables para demostrar el hecho:

SET @var:=5; 
SELECT IF(1 = 0, (@var:[email protected] + 1), @var); -- using ':=' operator to modify 'true' expr @var 
SELECT IF(1 = 1, @var, (@var:[email protected] + 1)); -- using ':=' operator to modify 'false' expr @var 
SELECT @var; 

El resultado es '5' de las tres consultas SELECT.

Si la función IF() NO estuviera en cortocircuito, el resultado sería un '5' de SELECT # 1, y '6' de SELECT # 2, y un '7' de la última "select @var".

Esto se debe a que la expresión 'verdadera' no se ejecuta NUNCA, en la selección n. ° 1 y tampoco se ejecuta la expresión falsa para la selección n. ° 2.

Tenga en cuenta que el operador ': =' se usa para modificar un @var, dentro de una consulta SQL (cláusulas select, from y where). Puede obtener un SQL realmente elegante/complejo a partir de esto. He usado @vars para aplicar la lógica 'procedural' dentro de una consulta SQL.

- J Jorgenson -

0

Depende.

SI hace provoque un cortocircuito de tal manera que se puede utilizar para evitar las advertencias de truncamiento con GROUP_CONCAT, por ejemplo en:

set @@group_concat_max_len = 5; 

select if(true or @var:=group_concat('warns if evaluated'), 'actual result', @var); 

el resultado será 'resultado real', sino que obtendrá una advertencia :

Warning (Code 1260): Row 1 was cut by GROUP_CONCAT() 

que es la misma advertencia que se obtiene con expresiones GROUP_CONCAT menos triviales, tales como claves distintas, y sin la SI en absoluto.

Cuestiones relacionadas