optimizar not lentas empty consultas check php mysql mysqli nullable prepared-statement

php - not - ¿Cadena vacía en la columna no nula en MySQL?



sql server is not null or empty (7)

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

Sin embargo, hay un problema con el que me estoy encontrando. Tengo una tabla con algunas columnas VARCHAR, que se especifican como no nulas (es decir, no permiten valores NULOS). 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 lanzará el error "el null value violates not-null constraint "

Como una solución temporal, compruebo si $value está vacío y lo cambio a " " (un espacio único), pero ese es un hack horrible y puede causar otros problemas.

¿Cómo se supone que insertar cadenas vacías con declaraciones preparadas, sin que intente en su lugar insertar un NULL?

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

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


¿No es un conjunto vacío de citas "" hacer eso?


Esto suena como un problema con la API de MDB2 buscando la semántica de tipado de pato de PHP. Debido a que la cadena vacía en PHP es equivalente a NULL, es probable que MDB2 lo maltrate como tal. La solución ideal sería encontrar una solución alternativa dentro de su API, pero no estoy demasiado familiarizado con ella.

Una cosa que debes considerar, sin embargo, es que una cadena vacía en SQL no es un valor NULL. Puede insertarlos en filas declaradas "NOT NULL" simplemente 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 de MDB2, una solución de seguridad (aunque ligeramente mejor que la que está utilizando actualmente) podría ser definir una 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 podría omitir la columna de la instrucción INSERT y se establecería automáticamente en la cadena vacía (siempre que la columna tenga una restricción NOT NULL).


Estoy confundido. Parece que estás usando mysqli OO (de las etiquetas y el estilo), pero la sintaxis es diferente del 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();


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 NOT NULL aunque el valor predeterminado es ""?
    • El problema es que para algunos RDBMS (el más notablemente Oracle), una cadena vacía es NULL. Por lo tanto, MDB2 proporciona una opción de portabilidad para aplicar el mismo comportamiento en todos los RDBMS.
    • Dado que todas las opciones de portabilidad están habilitadas de manera predeterminada, deberá deshabilitar la característica si no desea tener este comportamiento: $ mdb2-> setOption (''portabilidad'', MDB2_PORTABILITY_ALL ^ ​​MDB2_PORTABILITY_EMPTY_TO_NULL);

Gracias a todos los que proporcionaron respuestas reflexivas.


Me doy cuenta de que esta pregunta está prácticamente resuelta y retirada, pero la encontré al buscar respuestas a una situación similar y no puedo resistir arrojar mi sombrero al ring.

Sin saber a qué se refiere la columna NULL / "", no puedo saber cómo el verdadero significado de una cadena vacía. ¿Significa la cadena vacía algo en sí misma? (Por ejemplo, si convencí a un juez para que me permitiera cambiar mi nombre simplemente por nada), estaría realmente irritado si mi nombre apareciera en mi licencia de conducir como NULL. ¡Mi nombre sería!

Sin embargo, la cadena vacía (o espacio en blanco, o la nada que es ALGO, no simplemente la falta de algo (como NULO)) también podría simplemente significar simplemente "NO NULO" o "Nada, pero aún no es Nulo". Incluso puedes ir en la otra dirección y sugerir que la ausencia del valor NULL hace que sea incluso MENOS algo que nulo, porque al menos Null tiene un nombre que puedes 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 se inserta entre los números en mi número de teléfono, etc.), entonces las opciones son argumentar hasta que te duela para el uso legítimo de cadenas vacías o para usar algo que represente una cadena vacía que no sea NULL (como un carácter de control ASCII o algún equivalente en unicode, un valor de expresiones regulares de algún tipo o, peor aún, un token arbitrario pero totalmente inutilizado , como: ◘

Si la celda vacía realmente significa NOT NULL, entonces podrías pensar en alguna otra forma de expresarlo. Una manera tonta y obvia es la frase "No NULO". Pero tengo la corazonada de que NULL significa algo así como "No forma parte de este grupo en absoluto", mientras que la cadena vacía significa algo así como "este tipo es genial, todavía no ha recibido los tatuajes de su pandilla". En ese caso, se me ocurriría un término / nombre / idea para esta situación, como "predeterminado" o "novato" o "Pendiente".

Ahora, si por alguna loca casualidad quieres que una cuerda vacía represente aquello que ni siquiera es digno de NULL, de nuevo, obtén un símbolo más significativo para eso, como "-1" o "SUPERNULL" o "UGLIES".

En el sistema de casta indio, la casta más baja es Shudra: granjeros y obreros. Debajo de esta casta están los Dalit: "Los Intocables". No se consideran una casta inferior, porque establecerlos 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 NULAS!

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 manera 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 créeme, es mucho más fácil escribir una consulta para

SELECT * from table where mything IS NULL que para intentar consultar cadenas vacías: /