MySQL Forums
Forum List  »  Spanish

Re: Cómo crear un condicional en consulta en mi caso.
Posted by: Miguel Perez
Date: October 09, 2009 01:06AM

Lo que estás haciendo es extremadamente peligroso.

La razón por la que no te funciona la consulta es que no estás entrecomillando bien las cosas. Voy a usar siempre comillas simples para que sea más fácil de ver:
$sql = 'SELECT ... WHERE id = ' . $x;
Si $x es '123ABC', estás haciendo una consulta como 'SELECT ... WHERE c.id = 123ABC', que en SQL es ilegal y debería estar entrecomillada. Además, es malísimo. ¿Qué pasa si $x es '0;DELETE FROM xyz;'?

Intento de solución 1 (no es una solución, pero sígueme; y ahora voy a utilizar comillas dobles y simples, cuidado):
$sql = "SELECT ... WHERE id = '" . $x . "'"
Eso arregla lo de que $x sea '123ABC'. También es un lío por las comillas. Y lo peor es que sigue siendo una porquería. ¿Qué pasa si $x es exactamente "';DELETE FROM xyz;"?

(Nota: un defecto de PHP llamado "magic quotes" intenta paliar sin éxito estos casos. No uses magic quotes; deshabilítalas.)

Intento de solución 2: Hay que entrecomillar $x como se debe. Lo que deberías hacer, si estás utilizando la extensión vieja de MySQL, es:
$sql = sprintf("SELECT ... WHERE id = '%s'", mysql_real_escape_string($x));
Lo cual escapará correctamente $x. (Si estás usando la extensión mejorada mysqli, tienes que usar mysqli_real_escape_string en su lugar.) Y esto lo tienes que hacer para cada variable de cadena que quieras pasar, mientras que para cada variable numérica o de coma flotante lo que debes es convertirla con (int) o (float) para asegurarte de que es lo que tiene que ser al concatenarla y de que no tiene otros caracteres.

Como ves, es horrible. Las extensiones de PHP de MySQL siempre han tenido un soporte extremadamente deficiente para esto. Las cosas son ligeramente mejores con PDO, siempre que uses PDO::prepare y PDOStatement::execute y nunca PDO::query.

Una forma de utilizar de forma segura y racional las extensiones tradicionales de MySQL es crear una función que construya SQL de forma decente, como es habitual en otras APIs de otros lenguajes de programación. Aquí te paso como ejemplo una forma de hacerlo en PHP 5. Este código es Copyright (C) Afina Sistemas 2005-2009 y se distribuye bajo licencia de software libre GPL versión 3 (tres) o superior. Puedes utilizarlo en proyectos que distribuyas bajo la misma licencia, y distribuirlo bajo la misma licencia.
/**
 * Dato global necesario: Función que se necesita para escapar cadenas.
 * Configúrala de acuerdo a la base de datos que estás utilizando.
 */
$fdbquote = 'mysql_real_escape_string';


/**
 * Devuelve una representación en SQL de una variable. Los números se dejan como están; las cadenas
 * se escapan utilizando $fdbquote; null es NULL; los valores booleanos son 0 y 1; las listas se
 * convierten en una lista de valores separados por coma, cada uno procesado con var_SQLexport.
 */
function var_SQLexport($v) {
    if (is_string($v)) {
        return "'" . $GLOBALS['fdbquote']($v) . "'";
    } else if (is_null($v)) {
        return 'NULL';
    } else if (is_bool($v)) {
        return $v ? '1' : '0';
    } else if (is_array($v)) {
        foreach ($v as &$x) {
            $x = var_SQLexport($x);
        }
        return join(',', $v);
    } else {
        return (string) $v;
    }
}


/**
 * Devuelve una sentencia de SQL, sustituyendo cada "?" en $s por los parámetros adicionales
 * debidamente escapados. P.e. $país = 'España'; $número = 1; SQL('SELECT * FROM T WHERE
 * str = ? AND int = ?', $país, $número) devuelve "SELECT * FROM T WHERE str = 'España' AND
 * int = 1". No utilizar ? para nombres de tablas y otras cosas de SQL que no han de ser
 * entrecomilladas; en tal caso verificar la sanidad de los nombres (nunca deben ser entrados
 * por el usuario) y concatenarlos normalmente, quizás utilizando comillas dobles.
 */
function SQL($s /*, ...*/) {
	$param = func_get_args();
	$i = 1;
	return preg_replace('/\?/e', 'var_SQLexport($param[$i++])', $s);
}

Un saludo,

Miguel Pérez
Afina Sistemas - Partner de MySQL en España

Options: ReplyQuote


Subject
Views
Written By
Posted
Re: Cómo crear un condicional en consulta en mi caso.
6989
October 09, 2009 01:06AM


Sorry, you can't reply to this topic. It has been closed.

Content reproduced on this site is the property of the respective copyright holders. It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.