database-design - after - null object pattern java
¿Están bien los nulos en una base de datos relacional? (30)
Existe la creencia de que los valores nulos no deben permitirse en una base de datos relacional. Es decir, el atributo (columna) de una tabla no debe permitir valores nulos. Viniendo de un fondo de desarrollo de software, realmente no entiendo esto. Parece que si null es válido dentro del contexto del atributo, entonces debería permitirse. Esto es muy común en Java, donde las referencias de los objetos son a menudo nulas. Al no tener una amplia experiencia en bases de datos, me pregunto si me falta algo aquí.
Creo que está confundiendo el modelado conceptual de datos con el modelado de datos físicos.
En CDM, si un objeto tiene un campo opcional, debe subtipificar el objeto y crear un nuevo objeto para cuando ese campo no sea nulo. Esa es la teoría en los CDM
En el mundo físico hacemos todo tipo de compromisos para el mundo real. En el mundo real, los NULLS son más que buenos, son esenciales
Creo que la pregunta se reduce a lo que interpretas un valor de NULL para significar. Sí, hay muchas interpretaciones para un valor NULO, sin embargo, algunas de ellas publicadas aquí nunca deben usarse. El verdadero significado de NULL está determinado por el contexto de su aplicación y nunca debe significar más de una cosa. Por ejemplo, una sugerencia fue que NULL en un campo de fecha de nacimiento indicaría que la persona aún estaba viva. Esto es peligroso.
En toda simplicidad, defina NULL y cúmplalo. Lo uso para decir "el valor en este campo es desconocido en este momento". Significa eso y SÓLO eso. Si necesita que signifique algo más TAMBIÉN, entonces necesita volver a examinar su modelo de datos.
De acuerdo con el estricto álgebra relacional, los nulos no son necesarios. Sin embargo, para cualquier proyecto práctico, se necesitan.
En primer lugar, se desconocen muchos datos del mundo real o no son aplicables y los nulos implementan bien ese comportamiento. En segundo lugar, hacen que las vistas y las uniones externas sean mucho más prácticas.
Depende.
Mientras entiendas por qué permites NULL
en la base de datos ( la elección debe hacerse por columna ) Y cómo interpretarás, ignorarás o tratarás con ellos, están bien.
Por ejemplo, una columna como NUM_CHILDREN
, ¿qué haces si no sabes la respuesta? Debe ser NULL
. En mi opinión, no hay otra opción mejor para el diseño de esta columna (incluso si tiene un indicador para determinar si la columna NUM_CHILDREN
es válida, aún debe tener un valor en esta columna).
Por otro lado, si no permite valores NULL
y tiene valores reservados especiales para ciertos casos (en lugar de indicadores), como -1 para el número de hijos cuando es realmente desconocido, debe abordarlos de manera similar, en términos de convenciones, documentación, etc.
Por lo tanto, en última instancia, los problemas deben abordarse con convenciones, documentación y coherencia.
La alternativa, como aparentemente propugnada por Adam Davis en la respuesta anterior, de normalizar las columnas a escasa (o no tan dispersa, en el caso del ejemplo NUM_CHILDREN
o cualquier ejemplo donde la mayoría de los datos tenga valores conocidos) tablas, mientras para eliminar todos los NULL, no es viable en la práctica general.
En muchos casos en que se desconoce un atributo, tiene poco sentido unirse a otra tabla para cada columna que podría permitir NULL
s en un diseño más simple. La sobrecarga de las uniones, los requisitos de espacio para las teclas primarias tienen poco sentido en el mundo real.
Esto trae a la mente la forma en que las filas duplicadas pueden eliminarse agregando una columna de cardinalidad, mientras que teóricamente resuelve el problema de no tener una clave única, en la práctica que a veces es imposible, por ejemplo, en datos a gran escala. Los puristas son rápidos para sugerir un PK sustituto en su lugar, sin embargo, la idea de que un sustituto sin sentido puede formar parte de una tupla (fila) en una relación (tabla) es risible desde el punto de vista de la teoría relacional.
El problema principal con los nulos es que tienen una semántica especial que puede producir resultados inesperados con comparaciones, agregados y uniones.
Nada es igual a nulo, y nada nunca es igual a, mayor o menor que nulo, por lo que debe establecer valores nulos en un valor de marcador de posición si desea hacer una comparación masiva.
Esto también es un problema en las claves compuestas que podrían usarse en una combinación. Donde la clave natural incluye una columna que admite nulos, es posible que desee considerar el uso de una clave sintética.
Los valores nulos pueden caer fuera de los recuentos, que pueden no ser la semántica que deseas.
Los nulos en una columna a la que te puedes unir eliminarán las filas de una unión interna. En general, este es probablemente el comportamiento deseado, pero puede colocar trampas de elefantes para las personas que informan.
Hay bastantes otras sutilezas para los nulos. El SQL for Smarties de Joe Celko tiene un capítulo completo sobre el tema y es un buen libro y vale la pena leerlo de todos modos. Algunos ejemplos de lugares donde los nulos son una buena solución son:
Relaciones opcionales donde una entidad unida puede o no estar presente. Nulo es la única forma de representar una relación opcional en una columna de clave externa.
Columnas que puede utilizar para anular para abandonar los conteos.
Valores numéricos opcionales (por ejemplo, moneda) que pueden estar presentes o no. No existe un valor de marcador de posición efectivo para ''no registrado'' en sistemas numéricos (particularmente cuando cero es un valor legal), por lo que nulo es realmente la única buena manera de hacerlo.
Algunos ejemplos de lugares donde es posible que desee evitar el uso de valores nulos, ya que es probable que causen errores sutiles.
Valores ''No Grabados'' en campos de código con un FK contra una tabla de referencia. Utilice un valor de marcador de posición, para que usted (o algún analista de negocios aleatorio en la pista) no pierda inadvertidamente las filas de los conjuntos de resultados cuando realiza una consulta en la base de datos.
Campos de descripción donde no se ha ingresado nada - la cadena nula (
''''
) funciona bien para esto. Esto ahorra tener que tratar los nulos como un caso especial.Columnas opcionales en un sistema de informes o depósito de datos. Para esta situación, cree una fila de marcador de posición para "No grabado" en la dimensión y únase a eso. Esto simplifica las consultas y funciona muy bien con herramientas de informes ad-hoc.
Nuevamente, el libro de Celko es un buen tratamiento del tema.
En lugar de escribir todos los problemas de NULL, y tristate vs lógica booleana, etc., ofreceré este consejo conciso:
No permita NULL en sus columnas, hasta que encuentre que agrega un valor mágico para representar datos faltantes o incompletos.
Como hace esta pregunta, debe tener mucho cuidado con la forma en que se acerca a NULL. Hay muchas trampas no obvias. En caso de duda, no use NULL.
Encontrará con los sistemas de adquisición de datos paso a paso que no puede evitar tener nulos en una base de datos porque el orden de hacer preguntas / recopilación de datos rara vez coincide con el modelo de datos lógicos.
O puede establecer los valores por defecto (que requieren código para manejar estos valores predeterminados). Puede suponer que todas las cadenas están vacías en lugar de nulas, por ejemplo, en su modelo.
O bien, puede tener tablas de base de datos de etapas para la adquisición de datos que continúe hasta que se obtengan todos los datos antes de completar las tablas de la base de datos reales. Esto es mucho trabajo extra.
Está absolutamente bien con nulo.
Esta es una gran cantidad de gusanos, porque NULL puede significar muchas cosas:
- No hay fecha de muerte porque la persona todavía está viva.
- No hay número de teléfono celular porque no sabemos de qué se trata ni si existe.
- No hay número de seguro social porque se sabe que esa persona no tiene uno.
Algunos de estos pueden evitarse mediante la normalización, algunos de ellos pueden evitarse mediante la presencia de un valor en esa columna ("N / A"), algunos de ellos pueden mitigarse al tener una columna separada para explicar la presencia del NULL. ("N / K", "N / A", etc.)
También es una lata de gusanos porque la sintaxis SQL necesaria para encontrarlos es diferente a la de los valores que no son nulos, es difícil unirse a ellos, y generalmente no están incluidos en las entradas de índice.
Debido a la razón anterior, encontrarás casos en los que un nulo es inevitable.
Debido a esta última razón, debe hacer lo mejor para minimizar el número de ellos.
De todos modos, siempre use restricciones NOT NULL para protegerse contra valores nulos donde se requiere un valor.
Estoy de acuerdo con muchas de las respuestas anteriores y también creo que NULL se puede usar, según corresponda, en un diseño de esquema normalizado, particularmente donde puede evitar el uso de algún tipo de "número mágico" o valor predeterminado que, a su vez, podría ser engañoso!
Sin embargo, en última instancia, creo que el uso de null necesita estar bien pensado (en lugar de por defecto) para evitar algunas de las suposiciones enumeradas en las respuestas anteriores, particularmente donde se puede suponer que NULL es ''nada'' o ''vacío'', ''desconocido ''o el'' valor no se ha ingresado todavía ''.
Existe otra alternativa para usar "N / A" o "N / K" o la cadena vacía, una tabla separada.
Por ejemplo, si podemos o no podemos saber el número de teléfono de un cliente:
CREATE TABLE Customer (ID int PRIMARY KEY, Name varchar(100) NOT NULL, Address varchar(200) NOT NULL);
CREATE TABLE CustomerPhone (ID int PRIMARY KEY, Phone varchar(20) NOT NULL, CONSTRAINT FK_CustomerPhone_Customer FOREIGN KEY (ID) REFERENCES Customer (ID));
Si no conocemos el número de teléfono, simplemente no agregaremos una fila a la segunda tabla.
Hay varias objeciones diferentes al uso de NULL. Algunas de las objeciones se basan en la teoría de la base de datos. En teoría, no hay diferencia entre la teoría y la práctica. En la práctica, existe.
Es cierto que una base de datos totalmente normalizada puede funcionar sin NULLS en absoluto. Cualquier lugar donde el valor de los datos debe ser omitido es un lugar donde se puede omitir toda una fila sin pérdida de información.
En la práctica, la descomposición de tablas en este sentido no sirve para nada, y la programación necesaria para realizar operaciones CRUD simples en la base de datos se vuelve más tediosa y propensa a errores, en lugar de menos.
Hay lugares donde el uso de NULLS puede causar problemas: esencialmente, estos giran en torno a la siguiente pregunta: ¿qué significa realmente los datos faltantes? Todo lo que NULL realmente transmite es que no hay ningún valor almacenado en un campo dado. Pero las aplicaciones de inferencias que los programadores extraen de los datos faltantes a veces son incorrectas, y eso causa muchos problemas.
Es posible que falten datos de una ubicación por diversas razones. Aquí hay algunos:
Los datos son inaplicables en este contexto. por ejemplo, el primer nombre del cónyuge para una sola persona.
El usuario de un formulario de entrada de datos dejó un campo en blanco y la aplicación no requiere una entrada en el campo.
Los datos se copian en la base de datos desde otra base de datos o archivo, y faltaban datos en la fuente.
Hay una relación opcional codificada en una clave externa.
Una cadena vacía se almacenó en una base de datos Oracle.
Aquí hay algunas pautas sobre cuándo evitar NULLS:
Si en el curso de la programación normal esperada, los escritores de consultas tienen que escribir una gran cantidad de ISNULL, NV, COALESCE o un código similar para sustituir el valor NULL por uno válido. A veces, es mejor hacer la sustitución en el momento de la tienda, siempre que lo que se está almacenando sea "realidad".
Si es probable que los recuentos estén desactivados porque se contaron las filas que contienen un NULL. A menudo, esto puede obviarse simplemente seleccionando conteo (MyField) en lugar de conteo (*).
Aquí hay un lugar en el que mejor te acostumbras a NULLS, y programa en consecuencia: siempre que comiences a usar uniones externas, como LEFT JOIN y RIGHT JOIN. El punto entero detrás de una combinación externa como distinto de una unión interna es obtener filas cuando faltan algunos datos coincidentes. Los datos faltantes se darán como NULLS.
Mi conclusión: no descarte la teoría sin entenderla. Pero aprende cuándo apartarse de la teoría y cómo seguirla.
Lo mejor que debe saber sobre los formularios normales es que son guías y las guías no deben ser respetadas. Cuando el mundo de la academia choca con el mundo real rara vez se encuentran muchos guerreros supervivientes de acedemia.
La respuesta a esta pregunta es que está bien usar nulos. Simplemente evalúe su situación y decida si desea que aparezcan en la tabla o contraiga los datos en otra tabla relacionada si considera que la relación de valores nulos a valores reales es demasiado alta.
Como le gusta decir a un amigo: "No dejes que lo perfecto sea enemigo de lo bueno". Creo que Voltaire también dijo eso. 8)
Los marcadores nulos están bien. Realmente, lo son.
Los nulos pueden ser difíciles de trabajar, pero tienen sentido en algunos casos.
Supongamos que tiene una tabla de facturas con una columna "PaidDate" que tiene un valor de fecha. ¿Qué colocas en esa columna antes de pagar la factura (suponiendo que no sabes de antemano cuándo se pagará)? No puede ser una cadena vacía, porque esa no es una fecha válida. No tiene sentido darle una fecha arbitraria (por ejemplo, 1/1/1900) porque esa fecha simplemente no es correcta. Parece que el único valor razonable es NULL, porque no tiene un valor.
Trabajar con nulos en una base de datos tiene algunos desafíos, pero las bases de datos los manejan bien. Los problemas reales son cuando cargas nulos de tu base de datos en tu código de aplicación. Ahí es donde descubrí que las cosas son más difíciles. Por ejemplo, en .NET, una fecha en un conjunto de datos fuertemente tipado (que imita la estructura de su base de datos) es un tipo de valor y no puede ser nulo. Entonces tienes que construir soluciones.
Evita los nulos cuando puedas, pero no los descartes porque tienen usos válidos.
Los valores nulos se ven negativamente desde la perspectiva de la normalización de la base de datos. La idea es que si un valor no puede ser nada, entonces deberías dividirlo en otra tabla dispersa de manera que no necesites filas para los elementos que no tienen valor.
Es un esfuerzo para garantizar que todos los datos sean válidos y valiosos.
En algunos casos, tener un campo nulo es útil, especialmente cuando se quiere evitar otra unión por razones de rendimiento (aunque esto no debería ser un problema si el motor de la base de datos está configurado correctamente, excepto en escenarios extraordinarios de alto rendimiento).
-Adán
Mi opinión controvertida para el día: la opción predeterminada de permitir NULL en las columnas de la base de datos fue probablemente la peor decisión de diseño universalmente aceptada en todos los terrenos de RDBM. Cada vendedor lo hace, y está mal. Los NULL están bien en ciertas instancias específicas y bien pensadas, pero la idea de que debes rechazar explícitamente NULL para cada columna hace que la nulidad negligente sea más común de lo que debería ser.
NULL rocas. Si no fuera necesario en algunos casos, SQL no tendría IS NULL ni IS NULL como operadores de casos especiales. NULL es la raíz del conceptual universal, todo lo demás NO ES NULO. Use NULLs libremente, siempre que sea posible que un valor de datos esté ausente pero no perdido. Los valores predeterminados solo pueden compensar NULL si son absolutamente correctos todo el tiempo. Por ejemplo, si tengo un campo de un solo bit "IsReady", puede tener perfecto sentido para este campo tener un valor predeterminado de falso y NULL no permitido, pero esto afirma implícitamente que sabemos que lo que no está listo, cuando de hecho, es posible que no tengamos ese conocimiento. Lo más probable es que, en un escenario de flujo de trabajo, la persona que decide estar listo o no simplemente no haya tenido la oportunidad de ingresar su opinión todavía, por lo que un valor predeterminado de falso podría ser peligroso, lo que los lleva a pasar por alto una decisión que parece tener hecho, pero de hecho solo fue incumplido.
como un aparte, y en referencia al ejemplo inicial medio, mi padre no tenía segundo nombre, por lo tanto su inicial del segundo nombre sería NULL - no en blanco, espacio, o asterisco - excepto en el Ejército donde su inicial del segundo nombre era NMI = No Medio Inicial. ¿Qué tan tonto fue eso?
No hay nada de malo en usar NULL para campos de datos. Debe tener cuidado al establecer las claves en nulo. Las claves primarias nunca deben ser NULL. Las claves externas pueden ser nulas, pero debe tener cuidado de no crear registros huérfanos.
Si algo es "inexistente", entonces debe usar NULL en lugar de una cadena vacía u otro tipo de bandera.
No subestime la complejidad que crea haciendo que un campo sea NULLable. Por ejemplo, la cláusula where siguiente parece que coincidirá con todas las filas (los bits solo pueden ser 1 o 0, ¿no?)
where bitfield in (1,0)
Pero si el bitfield es NULLable, se perderá algo. O tome la siguiente consulta:
select * from mytable
where id not in (select id from excludetable)
Ahora, si la tabla de exclusión contiene un nulo y un 1, esto se traduce en:
select * from mytable
where id <> NULL and id <> 1
Pero "id <> NULL" es falso para cualquier valor de id, por lo que nunca devolverá ninguna fila. Esto atrapa incluso a los desarrolladores de bases de datos experimentados por surpise.
Dado que NULL puede sorprender a la mayoría de las personas con la guardia baja, trato de evitarlo cuando puedo.
No tomes mis palabras sarcásticas, lo digo en serio. A menos que esté trabajando con bases de datos de juguetes, los NULL son inevitables y en el mundo real no podemos evitar los valores NULL.
Solo por decir cómo puedes tener nombre, segundo nombre, apellido para cada persona. (El segundo nombre y el apellido son opcionales, en ese caso, los NULL están ahí para usted) y cómo puede tener el fax, el teléfono comercial, el teléfono de la oficina para todos en la lista de blogs.
NULLS están bien, y debes manejarlos adecuadamente cuando los recuperes. En SQL Server 2008 existe un concepto de columnas dispersas donde también se puede evitar el espacio ocupado para NULLs.
No confunda NULLs con ceros y cualquier otro valor. La gente hace que cualquiera diga que está bien.
Gracias Naveen
Para una base de datos, null se traduce como "No tengo valor para esto". Lo que significa que (curiosamente), una columna booleana que permite nulos es perfectamente aceptable y aparece en muchos esquemas de bases de datos. Por el contrario, si tiene un booleano en su código que puede tener un valor de ''verdadero'', ''falso'' o ''indefinido'', es probable que vea que su código finaliza en el día antes o después :)
Así que sí, si necesita permitir la posibilidad de que un campo no tenga ningún valor, entonces permitir nulos en la columna es perfectamente aceptable. Es significativamente mejor que las alternativas potenciales (cadenas vacías, cero, etc.)
Personalmente, creo que los valores nulos solo se deben usar cuando se utiliza el campo como una clave externa a otra tabla, para simbolizar que este registro no se vincula a nada en la otra tabla. Aparte de eso, encuentro que los valores nulos son realmente muy problemáticos cuando se programa la lógica de la aplicación. Debido a que no existe una representación directa de una base de datos nula en la mayoría de los lenguajes de programación para muchos tipos de datos, termina creando una gran cantidad de código de aplicación para tratar el significado de estos valores nulos. Cuando un DB encuentra un entero nulo e intenta, por ejemplo, agregarle un valor de 1 (también conocido como nulo + 1), la base de datos devolverá nulo, ya que así es como se define la lógica. Sin embargo, cuando un lenguaje de programación intenta agregar null y 1, por lo general lanzará una excepción. Entonces, su código termina lleno de verificaciones de qué hacer cuando el valor es nulo, lo que a menudo equivale a convertir a 0 para números, cadena vacía para texto y alguna fecha nula (1900/1/1?) Para campos de fecha .
Si bien técnicamente los NULL están bien como valor de campo, con bastante frecuencia no se respetan. Dependiendo de cómo se escriban los datos en su base de datos, es posible (y común) terminar con un valor de cadena vacío en el campo en lugar de un NULO. Por lo tanto, cualquier consulta que tenga este campo como parte de la cláusula WHERE, necesitaría manejar ambos escenarios que son pulsaciones de teclas innecesarias.
Técnicamente, los nulos son ilegales en las matemáticas relacionales en las que se basa la base de datos relacional. Entonces, desde el punto de vista del modelo relacional semántico, puramente técnico, no, no están bien.
En el mundo real, la desnormalización y algunas violaciones del modelo están bien. Pero, en general, los nulos son un indicador de que debe observar su diseño general más de cerca.
Siempre tengo mucho cuidado con los nulos y trato de normalizarlos siempre que puedo. Pero eso no significa que no sean la mejor opción a veces. Pero definitivamente me inclinaría hacia el lado de "sin nulos" a menos que estés realmente seguro de que tener los nulos es mejor en tu base particular.
Todo se reduce a la normalización frente a la facilidad de uso y los problemas de rendimiento.
Si va a seguir las reglas de normalización, terminará escribiendo cosas que se vean así:
Seleccione c.id, c.nombre anterior, ....... del cliente c left join customerphonenumber cpn en c.id = cpn.customerid left join customeraddress ca en c.id = ca.customerid left join customerphonenumber2 cpn2 en c. id = cpn2.customerid, etc., etc.
Un argumento en contra de los nulos es que no tienen una interpretación bien definida. Si un campo es nulo, podría interpretarse como cualquiera de los siguientes:
- El valor es "Nothing" o "Empty set"
- No hay ningún valor que tenga sentido para ese campo.
- El valor es desconocido.
- El valor no se ha ingresado todavía.
- El valor es una cadena vacía (para bases de datos que no distinguen entre nulos y cadenas vacías).
- Algún significado específico de la aplicación (por ej., "Si el valor es nulo, entonces use un valor predeterminado").
- Se ha producido un error que causa que el campo tenga un valor nulo cuando realmente no debería.
Algunos diseñadores de esquemas exigen que todos los valores y tipos de datos tengan interpretaciones bien definidas, por lo tanto, los nulos son malos.
Uno tiene que ver si estás usando una base de datos Oracle. Si guarda una cadena vacía en una columna de tipo CHAR, entonces Oracle forzará que el valor sea NULL sin preguntar. Por lo tanto, puede ser bastante difícil evitar valores NULL en columnas de cadena en Oracle.
Si está utilizando valores NULL, aprenda a usar el comando SQL COALESCE, especialmente con valores de cadena. A continuación, puede evitar que los valores NULL se propaguen en su lenguaje de programación. Por ejemplo, imagina a una persona que tiene un nombre, nombre medio y apellido pero quieres devolver un solo campo;
SELECT FullName = COALESCE(FirstName + '' '', '''') + COALESCE(MiddleName+ '' '', '''') + COALESCE(FamilyName, '''') FROM Person
Si no utiliza COALESCE, si alguna columna contiene un valor NULL , obtiene NULL devuelto.
Yo diría que los Nulls definitivamente deberían ser usados. No hay otra forma correcta de representar la falta de datos. Por ejemplo, sería incorrecto usar una cadena vacía para representar una línea de dirección faltante, o sería incorrecto usar 0 para representar un elemento de datos de edad faltante. Porque tanto una cadena vacía como 0 son datos. Null es la mejor manera de representar ese escenario.
null significa que no hay valor, mientras que 0 no, si ves un 0, no conoces el significado, si ves un valor nulo, sabes que es un valor perdido
Creo que los nulos son mucho más claros, 0 y '''' son confusos ya que no muestran claramente la intención del valor almacenado