SQL: cadena vacía vs valor NULL

69

Sé que este tema es un poco controvertido y hay muchos artículos / opiniones en internet. Desafortunadamente, la mayoría de ellos asume que la persona no sabe cuál es la diferencia entre NULL y una cadena vacía. Así que cuentan historias sobre resultados sorprendentes con uniones / agregados y generalmente hacen un poco más de lecciones avanzadas de SQL. Al hacer esto, fallan absolutamente todo el punto y por lo tanto son inútiles para mí. Así que espero que esta pregunta y todas las respuestas hagan avanzar un poco el tema.

Supongamos que tengo una tabla con información personal (nombre, nacimiento, etc.) donde una de las columnas es una dirección de correo electrónico con tipo varchar. Suponemos que, por algún motivo, es posible que algunas personas no deseen proporcionar una dirección de correo electrónico. Al insertar dichos datos (sin correo electrónico) en la tabla, hay dos opciones disponibles: establecer celda en NULL o configurarlo en cadena vacía (''). Supongamos que soy consciente de todas las implicaciones técnicas de elegir una solución en lugar de otra y puedo crear consultas SQL correctas para cada escenario. El problema es que incluso cuando ambos valores difieren en el nivel técnico, son exactamente iguales en el nivel lógico. Después de mirar NULL y '' llegué a una sola conclusión: no sé la dirección de correo electrónico del tipo. Además, no importa cuánto lo intenté, no pude enviar un correo electrónico utilizando NULL o una cadena vacía, por lo que aparentemente la mayoría de los servidores SMTP están de acuerdo con mi lógica. Así que tiendo a usar NULL donde no sé el valor y considero que una cadena vacía es algo malo.

Después de algunas discusiones intensas con colegas, llegué con dos preguntas:

  1. ¿Tengo razón al suponer que el uso de una cadena vacía para un valor desconocido está causando que una base de datos "mienta" sobre los hechos? Para ser más precisos: utilizando la idea de SQL de qué es valor y qué no lo es, podría llegar a una conclusión: tenemos una dirección de correo electrónico, solo descubriendo que no es nula. Pero luego, cuando intente enviar un correo electrónico, llegaré a una conclusión contradictoria: no, no tenemos una dirección de correo electrónico, ¡que @! # $ Database debe haber estado mintiendo!

  2. ¿Existe algún escenario lógico en el que una cadena vacía '' pueda ser un portador tan bueno de información importante (además de valor y ningún valor), que sería problemático / ineficiente de almacenar de otra manera (como información adicional)? columna). He visto muchas publicaciones que afirman que a veces es bueno usar una cadena vacía junto con valores reales y NULL, pero hasta ahora no he visto un escenario que sería lógico (en términos de diseño de SQL / DB).

P.S. Algunas personas se verán tentadas a responder que es solo una cuestión de gusto personal. No estoy de acuerdo Para mí es una decisión de diseño con importantes consecuencias. Así que me gustaría ver respuestas donde la opinión sobre esto esté respaldada por algunas razones lógicas y / o técnicas.

    
pregunta Jacek Prucia 30.12.2010 - 13:10

12 respuestas

82

Yo diría que NULL es la opción correcta para "sin dirección de correo electrónico". Hay muchas direcciones de correo electrónico "no válidas" y "" (cadena vacía) es solo una. Por ejemplo, "foo" no es una dirección de correo electrónico válida, "a @ b @ c" no es válida, etc. Así que solo porque "" no es una dirección de correo electrónico válida no es razón para usarla como el valor de "no dirección de correo electrónico".

Creo que tienes razón al decir que "" no es la forma correcta de decir "No tengo un valor para esta columna". "" es un valor.

Un ejemplo de donde "" podría ser un valor válido, separado de NULL podría ser el segundo nombre de una persona. No todos tienen un segundo nombre, por lo que debe diferenciar entre "sin segundo nombre" ("" - cadena vacía) y "No sé si esta persona tiene un segundo nombre o no" ( NULL ). Probablemente hay muchos otros ejemplos en los que una cadena vacía sigue siendo un valor válido para una columna.

    
respondido por el Dean Harding 30.12.2010 - 13:22
41

Mientras estoy de acuerdo con los comentarios anteriores, agregaría este argumento como motivación principal:

  1. Es obvio para cualquier programador que mira una base de datos que un campo marcado como NULO es un campo opcional. (es decir, el registro no requiere datos para esa columna)
  2. Si marca un campo NO NULO, cualquier programador debe asumir intuitivamente que es un campo obligatorio.
  3. En un campo que permite nulos, los programadores deben esperar ver nulos en lugar de cadenas vacías.

Por el bien de la codificación intuitiva de auto-documentación, use NULL en lugar de cadenas vacías.

    
respondido por el colinbashbash 14.09.2011 - 23:30
6

En su ejemplo, si es valor directamente del campo web, usaría una cadena vacía. Si el usuario tiene la opción de especificar que no desea proporcionar un correo electrónico o puede eliminarlo, entonces NULL.

Aquí hay un enlace con puntos que podría considerar: enlace

--- editado (En respuesta al comentario de Thomas) ---

Las bases de datos no viven sin las aplicaciones que las utilizan. La definición de NULL o "" no tiene ningún valor, si la aplicación no puede usarla correctamente.

Considere un ejemplo en el que el usuario llena el formulario LARGO y pulsa enter, que enviará una solicitud persistente al servidor. Él podría estar en el medio de introducir su correo electrónico. Lo más probable es que quieras guardar todo lo que tenga en el campo de correo electrónico, para que luego pueda terminarlo. ¿Qué pasa si él entró en un solo personaje? ¿Qué pasa si él ingresó un carácter y luego lo borra? Cuando el correo electrónico no es necesario, a veces los usuarios desean eliminarlo: la forma más sencilla de borrar el campo. También en caso de que no se requiera un correo electrónico, vale la pena validarlo antes de enviarlo.

Otro ejemplo: el usuario proporciona un correo electrónico como spam para @ [bigcompany] .com; en ese caso, no es necesario enviar un correo electrónico, incluso si existe y es válido (e incluso puede existir). El envío de uno de estos puede ser barato, pero si hay 10 mil usuarios con dichos correos electrónicos para suscripciones diarias, tal validación puede ahorrar mucho tiempo.

    
respondido por el Konstantin Petrukhnov 30.12.2010 - 13:41
4

Use Null.

No tiene sentido almacenar un valor de '', simplemente haciendo que el campo de la tabla sea nulable. También hace que las consultas sean más obvias.

¿Qué consulta SQL es más obvia y legible si desea encontrar usuarios con una dirección de correo electrónico?

  1. SELECT * FROM Users WHERE email_address != ''

  2. SELECT * FROM Users WHERE email_address IS NOT NULL

  3. SELECT * FROM Users WHERE email_address != '' and email_address IS NOT NULL

Yo diría que 2 es. Aunque 3 es más robusto en los casos en que se almacenan datos incorrectos.

Para el caso de la dirección de correo electrónico en el formulario, que es opcional, también debe reflejarse en la tabla. En SQL, es un campo que puede contener nulos, lo que significa que no se conoce.

No puedo pensar en ningún valor comercial razonable para almacenar una cadena vacía en una tabla que no sea simplemente un mal diseño. Es como almacenar un valor de cadena de 'NULL' o 'BLANK', y tener a los desarrolladores assume que es nulo o una cadena vacía. Para mí, eso es mal diseño. ¿Por qué almacenar eso cuando hay NULL?

Solo usa NULL, y harás a todos un poco más felices.

MÁS INFORMACIÓN:

SQL utiliza un sistema lógico de tres valores: Verdadero, Falso y Desconocido.

Para una explicación mejor y más detallada, recomiendo a los desarrolladores que lean: Consultas SQL: más allá de VERDADERO y FALSO .

    
respondido por el spong 15.09.2011 - 00:17
4

Creo que la respuesta de Dean Hardings cubre esto muy bien. Dicho esto, me gustaría mencionar que cuando se habla de NULLs vs cadenas vacías en el nivel de base de datos, debería tener en cuenta sus otros tipos de datos. ¿Almacenarías la fecha mínima cuando no hay fecha? o -1 cuando no se proporciona int? Almacenar un valor cuando no tiene un valor significa que debe realizar un seguimiento de todo un rango de valores distintos. Al menos uno para cada tipo de datos (posiblemente más a medida que obtenga casos donde -1 es un valor real, por lo que necesita tener alguna alternativa, etc.). Si necesita / quiere hacer algo "fudgy" en el nivel de la aplicación, eso es una cosa, pero no es necesario que contamine sus datos.

    
respondido por el bendemes 08.08.2012 - 11:18
4

Desafortunadamente, Oracle confundió la representación de la cadena VARCHAR de longitud cero con la representación de NULL. Ambos están representados internamente por un solo byte con valor cero. Esto hace que la discusión sea mucho más difícil.

Gran parte de la confusión que rodea a NULL se centra en lógica de tres valores . Considere el siguiente pseudocódigo:

if ZIPCODE = NULL
    print "ZIPCODE is NULL"
else if ZIPCODE <> NULL
    print "ZIPCODE is not NULL"
else print "Something unknown has happened"

No esperaría el tercer mensaje, pero eso es lo que obtendría, bajo la lógica de tres valores. Tres valiosas lógicas llevan a las personas a numerosos errores.

Otra fuente de confusión es sacar inferencias de la ausencia de datos, como sacar una inferencia del perro que no ladró en la noche. A menudo, estas inferencias no eran lo que el escritor de NULL tenía la intención de descubrir.

Habiendo dicho eso, hay muchas situaciones en las que NULL maneja la ausencia de datos muy bien y produce exactamente los resultados que desea. Un ejemplo son las claves externas en relaciones opcionales. Si utiliza un valor NULL para indicar que no hay relación en una fila determinada, esa fila se eliminará de una combinación interna, tal como lo esperaría.

Además, tenga en cuenta que incluso si evita NULLS completamente en los datos almacenados (sexta forma normal), si realiza cualquier combinación externa, aún tendrá que lidiar con NULLS.

    
respondido por el Walter Mitty 18.03.2011 - 05:16
3

para la pregunta técnica específica, el problema no es nulo frente a cadena vacía, es un error de validación . ¡Una cadena vacía no es una dirección de correo electrónico válida!

para la pregunta filosófica, la respuesta es similar: valida tus entradas. Si una cadena vacía es un valor válido para el campo en cuestión, espérelo y codifíquelo; si no, usa nulo.

Una cadena vacía sería una entrada válida para responder la pregunta: ¿Qué le dijo el mimo a la jirafa?

    
respondido por el Steven A. Lowe 30.12.2010 - 15:49
2

Podría pensar en una razón para tener NULL y la cadena vacía:

  • Tienes direcciones de correo electrónico válidas: [email protected]
  • No tiene ninguno (y probablemente debería pedir uno): NULL
  • Sabe que esta persona no tiene una dirección de correo electrónico: Empty String.

Sin embargo, no lo recomendaría y utilizaría un campo separado para preguntar si sabe que no existe ninguno.

    
respondido por el Marcel 15.01.2013 - 16:43
1

La pregunta, tal como la entiendo, es qué interpretaciones de NULL y cadena vacía se deben elegir. Esto depende de la cantidad de estados en que se encuentre el campo particualar.

La interpretación depende de cómo se accede a la base de datos. Si hay una capa en el código que extrae la base de datos completamente, entonces es completamente aceptable elegir cualquier política (incluyendo dos coulmn) que funcione. (Sin embargo, documentar claramente la política es importante). Sin embargo, si se accede a la base de datos en varios lugares, entonces debe usar un esquema muy simple, ya que el código será más difícil de mantener y puede ser erróneo en este caso.

    
respondido por el apoorv020 30.12.2010 - 14:05
1

Básicamente, en el nivel lógico, no hay diferencia entre el valor "no válido" y "sin entrada del usuario", son todos "casos especiales" la mayoría del tiempo. Caso de error.

Tener nulo ocupa espacio adicional: ceil (columns_with_null / 8) en bytes / por fila.

Las celdas vacías y las nulas son dos formas de marcar que algo está mal / debería ser predeterminado. ¿Por qué necesitarías 2 estados "incorrectos"? ¿Por qué usar NULL si ocupan espacio adicional y significan exactamente lo mismo que las cadenas vacías? Eso solo introducirá confusión y redundancia cuando tenga dos cosas que significan (lo que podría significar) exactamente lo mismo, es fácil olvidar que debe usar NULL en lugar de cadenas vacías (si, por ejemplo, el usuario ha asignado algunos campos).

Y tus datos pueden convertirse en un desastre. En un mundo perfecto dirías "los datos siempre serán correctos y los recordaré" ... pero cuando las personas tienen que trabajar en equipo y no todos están exactamente en tu nivel, no es raro ver DÓNDE (aa. xx < > '' AND bb.zz NO ES NULO)

Entonces, en lugar de corregir a los miembros de mi equipo cada dos días, solo aplico una regla simple. No hay valores nulos, NUNCA!

Contar valores NON-NULL es más rápido ... la pregunta simple es ¿para qué necesitarías hacer eso?

    
respondido por el Slawek 30.12.2010 - 15:35
1

Tiendo a verlo no desde la perspectiva de DB sino desde una perspectiva de programa. Sé que esta pregunta es para el clic de SQL, pero en realidad, ¿cuántos usuarios acceden a los datos directamente por más tiempo?

En un programa no me gusta nulo / nada. Hay algunas excepciones pero son solo eso. Y esas excepciones son realmente malas implementaciones.

Entonces, si el usuario no lo colocó en el correo electrónico, debería haber algo que determine si esto es válido o no. Si un correo electrónico en blanco está bien, entonces muestra una cadena en blanco. Si el usuario no ingresó un correo electrónico y eso viola una regla, el objeto debería indicar esto.

La idea de que nulo tenga significado es en la vieja escuela y es algo en lo que los programadores modernos tienen que trabajar.

Incluso en el diseño de DB, ¿por qué el campo de correo electrónico no permite nulos y tiene una cadena de longitud cero y tiene otro campo que indica si el usuario ingresó algo? ¿Un poco es mucho pedir a un DBMS? El DB no debería, en mi opinión, manejar ni la lógica de negocios ni la lógica de visualización. No fue construido para eso y por lo tanto hace un muy mal trabajo de manejo.

    
respondido por el ElGringoGrande 18.03.2011 - 05:48
-1

No creo que importe mucho, pero me gusta más cuando el NULL está allí.

Cuando veo los datos que se muestran en una tabla (como en SQL Server Management Studio), puedo distinguir mejor un valor faltante si dice NULL y el fondo es de diferente color.

Si veo un espacio en blanco, siempre me pregunto si está realmente vacío o si hay algún espacio en blanco o algunos caracteres invisibles. Con NULL, se garantiza que esté vacío a primera vista.

Normalmente no distingo los valores en la aplicación, porque es inesperado y extraño que NULL y una cadena vacía signifiquen algo diferente. Y la mayoría de las veces, adopto un enfoque defensivo y solo trato con ambos estados. Pero para mí, como humano, NULL es más fácil de procesar cuando se miran los datos.

    
respondido por el Tom Pažourek 11.08.2016 - 16:54

Lea otras preguntas en las etiquetas

Comentarios Recientes

La declaración NULL se ve mal porque la cadena vacía tiene un nuevo valor. No hay forma de llamar a la función mkstring de una cadena no NULL. Hay dos posibilidades posibles con valores nulos. En primer lugar, la cadena vacía puede consistir en dos cadenas diferentes. Sería fácil seguir esta regla simple multiplicando las dos cadenas para obtener un objeto de cadena, pero este método es más difícil de seguir en Python. Dejaré esto como un ejercicio para el lector para dar algunos comentarios para aclarar esto,... Lee mas