Sé que este tema es un poco controvertido y hay muchos artículos / opiniones que flotan en Internet. Desafortunadamente, la mayoría de ellos asume que la persona no sabe cuál es la diferencia entre una cadena NULL y vacía. Entonces cuentan historias sobre resultados sorprendentes con combinaciones / agregados y generalmente hacen lecciones de SQL un poco más avanzadas. Al hacer esto, se pierden absolutamente todo el punto y, por lo tanto, son inútiles para mí. Así que espero que esta pregunta y todas las respuestas avancen un poco hacia adelante.
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 alguna razón, algunas personas pueden no querer proporcionar una dirección de correo electrónico. Al insertar dichos datos (sin correo electrónico) en la tabla, hay dos opciones disponibles: establecer la celda en NULL o establecerla en una cadena vacía (''). Supongamos que conozco todas las implicaciones técnicas de elegir una solución sobre otra y puedo crear consultas SQL correctas para cualquier 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 chico. Además, no importa cuánto lo intente, No pude enviar un correo electrónico usando 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 la cadena vacía es algo malo.
Después de algunas discusiones intensas con colegas, llegué con dos preguntas:
¿estoy en lo cierto 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: usando la idea de SQL de lo que es valor y lo que no lo es, podría llegar a una conclusión: tenemos una dirección de correo electrónico, solo al descubrir 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, ¡esa base de datos @! # $ Debe haber estado mintiendo!
¿Hay algún escenario lógico en el que una cadena vacía '' podría ser un buen portador de información importante (además del valor y ningún valor), que sería problemático / ineficiente para almacenar de cualquier otra manera (como una columna adicional). 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 sea lógico (en términos de diseño de SQL / DB).
PD: 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.
''
incluso en Oracle, no es lo mismo queNULL
. Por ejemplo, asignarle unaCHAR(1)
columna al valor''
dará como resultado' '
(es decir, un espacio), noNULL
. Además, si Jacek usara Oracle, esta pregunta probablemente ni siquiera surgiría :-)'' IS NULL
evalúatrue
en PL / SQL.Respuestas:
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. Entonces, el hecho de que "" no sea una dirección de correo electrónico válida no es motivo para usarlo como el valor de "sin dirección de correo electrónico".Creo que tiene 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 dónde "" 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 haya muchos otros ejemplos en los que una cadena vacía sigue siendo un valor válido para una columna.fuente
NULL
que no significa que no haya una dirección de correo electrónico, creo que significa que la dirección de correo electrónico actualmente no se conoce, no se sabe que existe o es imposible de completar por otras razones. Afortunadamente, es probable que no haya una situación en la que uno quiera mantener en una base de datos la información sobre las personas que realmente no tienen y no planean tener ninguna dirección de correo electrónico, de lo contrario, probablemente sería necesario un campo booleano separado.Si bien estoy de acuerdo con los comentarios anteriores, agregaría este argumento como motivación principal:
En aras de la codificación intuitiva autodocumentada, use NULL en lugar de cadenas vacías.
fuente
En su ejemplo, si es un valor directamente del campo web, usaría una cadena vacía. Si el usuario puede optar por especificar que no desea proporcionar correo electrónico, o puede eliminarlo, entonces NULL.
Aquí hay un enlace con puntos que podría considerar: https://stackoverflow.com/questions/405909/null-vs-empty-when-dealing-with-user-input/405945#405945
--- editado (en respuesta al comentario de Thomas) ---
Las bases de datos no viven sin aplicaciones que las usen. Definir NULL o '' no tiene valor, si la aplicación no puede usarlo correctamente.
Considere un ejemplo donde el usuario está completando un formulario LARGO y presione enter, que enviará una solicitud persistente al servidor. Él podría estar en medio de ingresar su correo electrónico. Lo más probable es que desee almacenar lo que tenga en el campo de correo electrónico, para que luego pueda terminarlo. ¿Qué pasa si ingresó un solo personaje? ¿Qué pasa si ingresó un carácter y luego lo borró? Cuando no se requiere correo electrónico, a veces los usuarios desean eliminarlo: la forma más fácil de borrar el campo. También en caso de que no se requiera correo electrónico, vale la pena validarlo antes de enviarlo.
Otro ejemplo: el usuario proporciona correo electrónico como spamto @ [bigcompany] .com; en ese caso, no es necesario enviar correo electrónico, incluso si existe y es válido (e incluso puede existir). Enviar uno de estos puede ser barato, pero si hay 10K usuarios con tales correos electrónicos para suscripciones diarias, tal validación puede ahorrar mucho tiempo.
fuente
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, debe pensar en sus otros tipos de datos. ¿Almacenaría la fecha mínima cuando no se proporciona una fecha? o -1 cuando no se suministra int? Almacenar un valor cuando no tiene ningún valor significa que debe realizar un seguimiento de un rango completo de valores no. Al menos uno para cada tipo de datos (posiblemente más a medida que obtiene casos donde -1 es un valor real, por lo que necesita tener alguna alternativa, etc.). Si necesita / quiere hacer algo "falso" a nivel de aplicación, eso es una cosa, pero no es necesario contaminar sus datos.
fuente
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 la lógica de tres valores . Considere el siguiente pseudocódigo:
No esperaría el tercer mensaje, pero eso es lo que obtendría, bajo una lógica de tres valores. La lógica de tres valores lleva a las personas hacia 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 del NULL pretendía transmitir.
Dicho esto, hay muchas situaciones en las que NULL maneja bien la ausencia de datos y produce exactamente los resultados que desea. Un ejemplo son las claves foráneas en relaciones opcionales. Si usa un NULL para indicar que no hay relación en una fila determinada, esa fila se eliminará de una unión interna, tal como era de esperar.
Además, tenga en cuenta que incluso si evita los NULLS por completo en los datos almacenados (sexta forma normal), si realiza uniones externas, aún tendrá que hacer frente a NULLS.
fuente
Usar nulo.
No tiene sentido almacenar un valor de '', cuando simplemente se puede anular el campo en la tabla. 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?
SELECT * FROM Users WHERE email_address != ''
SELECT * FROM Users WHERE email_address IS NOT NULL
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 hay datos incorrectos almacenados.
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 anulable, 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 diseño incorrecto. Es como almacenar un valor de cadena de 'NULL' o 'BLANK', y hacer que los desarrolladores supongan que es una cadena nula o vacía. Para mí, eso es un mal diseño. ¿Por qué almacenar eso cuando hay NULL?
Simplemente use NULL y hará que todos estén 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 .
fuente
Para la pregunta técnica específica, el problema no es nulo frente a una 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: validar sus entradas. Si una cadena vacía es un valor válido para el campo en cuestión, espere y codifíquelo; si no, use nulo.
Una cadena vacía sería una entrada válida para responder la pregunta: ¿Qué le dijo el mimo a la jirafa?
fuente
Podría pensar en una razón para tener NULL y la cadena vacía:
[email protected]
NULL
Empty String.
Sin embargo, no recomendaría eso y usaría un campo separado para preguntar si sabe que no existe ninguno.
fuente
La pregunta, según tengo entendido, es qué interpretaciones de NULL y cadena vacía deben elegirse. Esto depende de cuántos estados pueda estar el campo particular.
La interpretación depende de cómo se accede a la base de datos. Si hay una capa en el código que abstrae la base de datos por completo, entonces elegir cualquier política (incluyendo dos coulmn) que funcione es completamente aceptable. (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.
fuente
Básicamente, en el nivel lógico, no hay diferencia entre el valor "no válido" y "ninguna entrada del usuario", son solo "casos especiales" la mayoría de las veces. Caso de error
Tener nulo requiere espacio adicional: ceil (columnas_con_nulo / 8) en bytes / por fila.
Celda vacía y nulo son ambas 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 (que podrían significar) exactamente lo mismo, es fácil olvidar que debe usar NULL en lugar de cadenas vacías (si, por ejemplo, el usuario omitió algunos campos).
Y sus datos pueden convertirse en un desastre. En un mundo perfecto, diría "los datos siempre serán correctos y lo recordaré" ... pero cuando las personas tienen que trabajar en un equipo y no todos están exactamente a su nivel, no es raro ver DONDE (aa. xx <> '' Y bb.zz NO ES NULO)
Entonces, en lugar de corregir a los miembros de mi equipo cada dos días, simplemente impongo una regla simple. Sin valores nulos, NUNCA!
Contar valores NO NULOS es más rápido ... una simple pregunta es ¿para qué necesitarías hacer eso?
fuente
VARCHAR
columna tomará al menos 1 byte para almacenar la longitud de la cadena, incluso si es cero.Tiendo a verlo no desde la perspectiva DB sino desde la perspectiva de un 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 solo malas implementaciones.
Entonces, si el usuario no ingresó 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 debe indicarlo.
La idea de que nulo tiene significado es de la vieja escuela y es algo que los programadores modernos deben resolver.
Incluso en el diseño de base de datos, ¿por qué el campo de correo electrónico no puede permitir valores nulos y tener una cadena de longitud cero y tener otro campo que indique si el usuario ingresó algo? ¿Es mucho pedirle a un DBMS? El DB no debería, en mi opinión, no 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 trabajo muy pobre al manejarlo.
fuente
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 un color diferente.
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 vacío a primera vista.
Por lo general, 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 al mirar los datos.
fuente