MySQL, mejor insertar una cadena NULL o vacía?

230

Tengo un formulario en un sitio web que tiene muchos campos diferentes. Algunos de los campos son opcionales, mientras que otros son obligatorios. En mi DB tengo una tabla que contiene todos estos valores, ¿es una mejor práctica insertar un valor NULL o una cadena vacía en las columnas de DB donde el usuario no puso ningún dato?

roflwaffle
fuente

Respuestas:

220

Al usar NULLpuede distinguir entre "no poner datos" y "poner datos vacíos".

Algunas diferencias más:

  • A LENGTHde NULLis NULL, a LENGTHde una cadena vacía es 0.

  • NULLs se ordenan antes de las cadenas vacías.

  • COUNT(message)contará cadenas vacías pero no NULLs

  • Puede buscar una cadena vacía utilizando una variable enlazada pero no a NULL. Esta consulta:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    Nunca coincidirá con una NULLde mytext, cualquier valor que se pasa desde el cliente. Para hacer coincidir NULLs, deberá usar otra consulta:

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL
Quassnoi
fuente
3
pero cuál crees que es más rápido? 0 o NULL o ""
Atul Dravid
8
en InnoDB NULL ocupan menos espacio
Timo Huovinen
37
Creo que esta es una respuesta correcta, pero también ignora totalmente el elemento de "mejor práctica" de la pregunta y solo se enfoca en hechos tangencialmente relevantes (¿orden de clasificación NULL y longitud? Estos no importan). En la mayoría de los tipos de entrada de datos de texto no hay una diferencia entre "sin respuesta" y "respuesta vacía", por lo que creo que esta es una gran pregunta que merece una mejor respuesta.
Nick
66
Los NULL también funcionan muy bien cuando se establece el campo ÚNICO. Por ejemplo, si tiene un campo como Licencia de conducir para agregar el número DL de la persona y el tipo no lo tiene. Dado que es un campo único, se agregará la primera persona sin DL No. pero no la siguiente, ya que arrojará un error de restricción única. Entonces, NULL es mejor.
Saifur Rahman Mohsin
1
@Quassnoi, lo siento ... Quiero decir, ¿por qué es una mala práctica establecer la licencia de conducir como única ...?
cedbeu
44

Una cosa a tener en cuenta, si alguna vez planea cambiar bases de datos, es que Oracle no admite cadenas vacías . Se convierten a NULL automáticamente y no puede consultarlos utilizando cláusulas como WHERE somefield = ''.

Matt Solnit
fuente
11
Esto me pareció increíblemente sospechoso, incluso en su enlace, así que lo intenté. Campo nulo, establecido en '', Oracle lo ignora. La longitud de los informes es nula en lugar de 0. Eso está muy mal. Tiene que haber alguna forma de evitar esto. Creo que publicaré esto como otra pregunta.
Steve B.
1
Steve B.: vea esta pregunta: stackoverflow.com/questions/1171196/…
Quassnoi
Gracias por la referencia, aunque todavía no entiendo el razonamiento. Publicado como stackoverflow.com/questions/1268177/…
Steve B.
Podría valer la pena actualizar la respuesta para incluir información del enlace publicado por Quassnoi
SamuelKDavis el
77
Peoplesoft (con Oracle DB) usa un solo espacio para indicar un valor vacío. Increíblemente estúpido. También usan 0.00025 para indicar 0 para FTE ya que 0 no está permitido. Se hicieron elecciones encantadoras en ese producto.
JP Duffy
9

Una cosa a tener en cuenta es que NULL podría dificultar mucho más sus rutas de código. En Python, por ejemplo, la mayoría de los adaptadores de bases de datos / ORM se asignan NULLa None.

Entonces cosas como:

print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow

podría dar como resultado "¡Hola, Joe Doe!" Para evitarlo, necesita algo como este código:

if databaserow.title:
    print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
    print "Hello, %(firstname) %(lastname)!" % databaserow

Lo que puede hacer las cosas mucho más complejas.

max
fuente
25
En mi opinión, abusar de su base de datos para "corregir" errores en su código o el marco es una práctica de codificación (muy) mala. Cuando no hay datos, simplemente debe insertar NULL y ser coherente en su uso. De lo contrario, debe usar declaraciones como: if (myString == null || myString = ""). Cuando un objeto no está establecido o definido en su código, también está usando NULL en lugar de algún tipo de "marcador de posición" (que en mi opinión es una cadena vacía).
Gertjan
55
Depende mucho de su idioma de elección. En Python "si no myString:" prueba para Ninguno y "". Probablemente principalmente una cuestión cultural. La "mala práctica" de Java Guys es la elegancia de la persona dinámica.
max
9

Es mejor insertar NULLpor coherencia en su base de datos en MySQL. Las claves externas se pueden almacenar como, NULLpero NO como cadenas vacías.

Tendrá problemas con una cadena vacía en las restricciones. Puede que tenga que insertar un registro falso con una cadena vacía única para satisfacer una restricción de clave externa. Mala práctica, supongo.

Ver también: ¿Puede una clave foránea ser NULL y / o duplicarse?

micaball
fuente
El problema de las restricciones me ha hecho tropezar en el pasado, por eso es que "hago +1" esta respuesta.
HPWD
Pero si usa NULL, asegúrese de que nunca termine con cadenas vacías también. Fácil de hacer con muchas tecnologías de interfaz de usuario.
Aplicable el
5

No sé cuál sería la mejor práctica aquí, pero generalmente erraría a favor de nulo a menos que desee que nulo signifique algo diferente de cadena vacía, y la entrada del usuario coincida con su definición de cadena vacía.

Tenga en cuenta que estoy diciendo que USTED necesita definir cómo quiere que sean diferentes. A veces tiene sentido tenerlos diferentes, a veces no. Si no, simplemente elige uno y quédate con él. Como dije, tiendo a favorecer el NULL la mayor parte del tiempo.

Ah, y tenga en cuenta que si la columna es nula, es menos probable que el registro aparezca en prácticamente cualquier consulta que seleccione (tiene una cláusula where, en términos SQL) basada en esa columna, a menos que la selección sea para una columna nula por supuesto.

Azul platino
fuente
1
... Y ahora que veo la respuesta por encima de mí, creo que es seguro decir que la diferenciación habitual que le interesaría es sin datos versus datos vacíos. :-)
Platinum Azure
1

Si está utilizando varias columnas en un índice único y al menos una de estas columnas es obligatoria (es decir, un campo de formulario obligatorio), si establece las otras columnas en el índice como NULL, puede terminar con filas duplicadas. Esto se debe a que los valores NULL se ignoran en columnas únicas. En este caso, use cadenas vacías en las otras columnas del índice único para evitar filas duplicadas.

COLUMNAS EN UN ÍNDICE ÚNICO:
(event_type_id, event_title, date, location, url)

EJEMPLO 1:
(1, 'BBQ', '2018-07-27', nulo, nulo)
(1, 'BBQ', '2018-07-27', null, null) // permitido y duplicado.

EJEMPLO 2:
(1, 'BBQ', '2018-07-27', '', '')
(1, 'BBQ', '2018-07-27', '', '') // NO está permitido ya que está duplicado.

Aquí hay algunos códigos:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `event_title` varchar(50) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `location` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Ahora inserte esto para ver que permitirá las filas duplicadas:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

Ahora inserte esto y verifique que no esté permitido:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

Entonces, no hay correcto o incorrecto aquí. Depende de usted decidir qué funciona mejor con sus reglas comerciales.

João Marques
fuente