Pregunta

Solía ??usar las declaraciones estándar mysql_connect (), mysql_query (), etc. para hacer cosas de MySQL desde PHP. Últimamente he estado cambiando para usar la maravillosa clase MDB2. Junto con esto, estoy usando declaraciones preparadas, por lo que no tengo que preocuparme por escapar de mis ataques de entrada y de inyección SQL.

Sin embargo, hay un problema con el que me encuentro. Tengo una tabla con algunas columnas VARCHAR, que se especifican como no nulas (es decir, no permiten valores NULL). Usando los viejos comandos PHP de MySQL, podría hacer cosas como esta sin ningún problema:

INSERT INTO mytable SET somevarchar = '';

Ahora, sin embargo, si tengo una consulta como:

INSERT INTO mytable SET somevarchar = ?;

Y luego en PHP tengo:

$value = "";
$prepared = $db->prepare($query, array('text'));
$result = $prepared->execute($value);

Esto arrojará el error " el valor nulo viola la restricción no nula "

Como solución temporal, verifico si $ value está vacío, y lo cambio a " " (un solo espacio), pero es un truco horrible y puede causar otros problemas.

¿Cómo se supone que debo insertar cadenas vacías con sentencias preparadas, sin que intente insertar un NULL?

EDITAR: es un proyecto demasiado grande para revisar toda mi base de código, encontrar en todas partes que use una cadena vacía " " y cámbielo para usar NULL en su lugar. Lo que necesito saber es por qué las consultas estándar de MySQL tratan " " y NULL como dos cosas separadas (como creo que es correcto), pero las declaraciones preparadas convierten " " en NULL.

Tenga en cuenta que " " y NULL son no lo mismo. Por ejemplo, SELECT NULL = " " ;; devuelve NULL en lugar de 1 como cabría esperar.

¿Fue útil?

Solución

Esto suena como un problema con la API MDB2 que busca la semántica de tipeo de PHP. Debido a que la cadena vacía en PHP es equivalente a NULL, MDB2 probablemente lo esté tratando mal como tal. La solución ideal sería encontrar una solución dentro de su API, pero no estoy demasiado familiarizado con él.

Sin embargo, una cosa que debe considerar es que una cadena vacía en SQL no es un valor NULL. Puede insertarlos en filas declaradas 'NO NULAS' muy bien:

mysql> CREATE TABLE tbl( row CHAR(128) NOT NULL );
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO tbl VALUES( 'not empty' ), ( '' );
Query OK, 2 rows affected (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT row, row IS NULL FROM tbl;
+-----------+-------------+
| row       | row IS NULL |
+-----------+-------------+
| not empty |           0 | 
|           |           0 | 
+-----------+-------------+
2 rows in set (0.00 sec)

mysql> INSERT INTO tbl VALUES( NULL );
ERROR 1048 (23000): Column 'row' cannot be null

Si no puede encontrar (o implementar) una solución alternativa en la API MDB2, una solución hack (aunque un poco mejor que la que está usando actualmente) podría ser definir un variable de usuario para la cadena vacía -

SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;

Finalmente, si necesita usar la cadena vacía en una instrucción INSERT pero no puede hacerlo, el valor predeterminado para los tipos de cadena en MySQL es una cadena vacía. Entonces, simplemente puede omitir la columna de la instrucción INSERT y se establecerá automáticamente en la cadena vacía (siempre que la columna tenga una restricción NOT NULL).

Otros consejos

Gracias a algunas de las respuestas, me di cuenta de que el problema puede estar en la API MDB2 y no en los comandos PHP o MYSQL. Efectivamente, encontré esto en las preguntas frecuentes de MDB2:

  
      
  • ¿Por qué las cadenas vacías terminan como NULL en la base de datos? ¿Por qué obtengo un NULL?   no permitido en campos de texto NO NULL   aunque el valor predeterminado es " " ;?      
        
    • El problema es que para algunos RDBMS (más notablemente Oracle) un vacío   la cadena es NULL. Por lo tanto MDB2   proporciona una opción de portabilidad para   hacer cumplir el mismo comportamiento en todos   RDBMS.
    •   
    • Dado que todas las opciones de portabilidad están habilitadas de forma predeterminada, tendrá   para deshabilitar la función si no   quiere tener este comportamiento:   $ mdb2- > setOption ('portabilidad',   MDB2_PORTABILITY_ALL ^   MDB2_PORTABILITY_EMPTY_TO_NULL);
    •   
  •   

Gracias a todos los que proporcionaron respuestas bien pensadas.

Me doy cuenta de que esta pregunta está bastante respondida y retirada, pero la encontré mientras buscaba respuestas a una situación similar y no puedo resistirme a tirar mi sombrero al ring.

Sin saber cuál es el NULL / " " columna se refiere a, no puedo saber cómo el verdadero significado de una cadena vacía. ¿La cadena vacía significa algo en sí mismo (por ejemplo, si convenciera a un juez de que me permitiera cambiar mi nombre a simplemente nada, me enojaría mucho si mi nombre apareciera en mi Licencia de conducir como NULL. ¡Mi nombre sería! >

Sin embargo, la cadena vacía (o en blanco, o la nada que es ALGO, no simplemente la falta de algo (como NULL)) también podría significar simplemente "NOT NULL". o "Nada, pero todavía no es Nulo". Incluso podría ir en la otra dirección y sugerir que la ausencia del valor NULL hace que sea MENOS que Null, ¡porque al menos Null tiene un nombre que puede decir en voz alta!

Mi punto es que si la cadena vacía es una representación directa de algunos datos (como un nombre, o lo que prefiero que se inserte entre los números en mi número de teléfono, etc.), entonces sus opciones son discutir hasta que usted Estás adolorido por el uso legítimo de una cadena vacía o por usar algo que representa una cadena vacía que no es NULL (como un carácter de control ASCII o algún equivalente Unicode, un valor regex de algún tipo o, peor aún, un arbitrario aún ficha totalmente no utilizada, como: ?

Si la celda vacía realmente significa NO NULL, entonces podría pensar en alguna otra forma de expresarla. Una forma tonta y obvia es la frase "No NULL". Pero tengo el presentimiento de que NULL significa algo así como "No es parte de este grupo en absoluto" mientras que la cadena vacía significa algo así como "este tipo es genial, simplemente todavía no se ha hecho sus tatuajes de pandillas". En cuyo caso, se me ocurriría un término / nombre / idea para esta situación, como "predeterminado". o "novato" o "Pendiente".

Ahora, si por casualidad quieres que la cadena vacía represente lo que ni siquiera es digno de NULL, de nuevo, encuentra un símbolo más significativo para eso, como '' -1 '' o "SUPERNULL" o " UGLIES " ;.

En el sistema de castas de la India, las castas más bajas son Shudra: agricultores y trabajadores. Debajo de esta casta están los Dalit: "Los intocables". No se consideran una casta inferior, porque establecerlas como la casta más baja se consideraría una contaminación de todo el sistema.

¡Así que no me llames loco por pensar que las cadenas vacías pueden ser PEOR que NULL!

'Hasta la próxima.

¡Encontré la solución!

MDB2 convierte cadenas vacías a NULL porque la opción de portabilidad MDB2_PORTABILITY_EMPTY_TO_NULL está activada de forma predeterminada (gracias a Oracle que considera que las cadenas vacías son nulas).

Desactive estas opciones cuando se conecte a la base de datos:

$options = array(
    'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL
);
$res= & MDB2::connect("mysql://user:password@server/dbase", $options);

Mientras que 0 y las cadenas vacías son variables, NULL es la ausencia de datos. Y confía en mí, es mucho más fácil escribir una consulta en

SELECT * de la tabla donde mything IS NULL que intentar buscar cadenas vacías: /

¿No hace eso un conjunto vacío de comillas, " " ?

Estoy confundido. Parece que está utilizando mysqli OO (de las etiquetas y el estilo), pero la sintaxis es diferente de la manual en php.net, que dice hacer esto en su lugar:

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top