¿Uso estándar de 'Z' en lugar de NULL para representar datos faltantes?

Fuera del argumento de si se deben usar NULL o no: soy responsable de una database existente que usa NULL para indicar datos "faltantes o nunca ingresados". Es diferente de una cadena vacía, lo que significa que "un usuario estableció este valor y seleccionó 'vacío'".

Otro contratista en el proyecto está firmemente en "NULLs no existen para mí, nunca uso NULL y nadie más debería, tampoco" lado del argumento. Sin embargo, lo que me confunde es que dado que el equipo del contratista RECONOCE la diferencia entre "faltante / nunca ingresado" e "intencionalmente vacío o indicado por el usuario como desconocido", usan un solo carácter "Z" en todo su código y procedimientos almacenados para representar "faltante / nunca ingresado" con el mismo significado que NULL en el rest de la database.

Aunque nuestro cliente compartido ha pedido que se cambie esto, y he respaldado esta request, el equipo cita esto como "práctica estándar" entre los administradores de bases de datos mucho más avanzados que yo; son reacios a cambiar para usar NULL basados ​​solo en mi request ignorante. Entonces, ¿alguien puede ayudarme a superar mi ignorancia? ¿Hay algún estándar, o pequeño grupo de personas, o incluso una única voz alta entre los expertos SQL que defienda el uso de 'Z' en lugar de NULL?

Actualizar

Tengo una respuesta del contratista para agregar. Esto es lo que dijo cuando el cliente solicitó que se eliminaran los valores especiales para permitir NULL en columnas sin datos:

Básicamente, diseñé la database para evitar valores NULL siempre que sea posible. Aquí está el razonamiento:

Un NULL en un campo de cadena [VARCHAR] nunca es necesario porque una cadena vacía (longitud cero) proporciona exactamente la misma información.

Un NULL en un campo integer (p. Ej., Un valor de ID) puede manejarse usando un valor que nunca ocurriría en los datos (p. Ej., -1 para un campo de IDENTIDAD entera).

Un NULL en un campo de date fácilmente puede causar complicaciones en los cálculos de date. Por ejemplo, en la lógica que calcula las diferencias de dates, como la diferencia en días entre [Fecha de recuperación] y [Fecha de input], la lógica explotará si una o ambas dates son NULAS, a less que se haga una asignación explícita para ambas dates siendo NULL Eso es trabajo extra y manejo extra. Si se usan dates "pnetworkingeterminadas" o "placeholder" para [Fecha de recuperación] y [Fecha de input] (por ejemplo, "1/1/1900"), los cálculos matemáticos pueden mostrar valores "inusuales", pero la lógica de la date no explotará.

El manejo NULL ha sido tradicionalmente un área donde los desarrolladores cometen errores en los procedimientos almacenados.

En mis 15 años como DBA, he encontrado que es mejor evitar NULLs siempre que sea posible.

Esto parece validar la reacción más negativa a esta pregunta. En lugar de aplicar un enfoque aceptado de 6NF para diseñar valores NULL, se usan valores especiales para "evitar valores NULL siempre que sea posible". Publiqué esta pregunta con una mente abierta, y estoy contento de haber aprendido más sobre el debate "Los NULL son útiles / los NULL son malvados", pero ahora me siento bastante cómodo labelndo el enfoque de "valores especiales" como una completa tontería.

una cadena vacía (de longitud cero) proporciona exactamente la misma información.

No, no es así. en la database existente que estamos modificando, NULL significa "nunca ingresado" y cadena vacía significa "ingresado como vacío".

El manejo NULL ha sido tradicionalmente un área donde los desarrolladores cometen errores en los procedimientos almacenados.

Sí, pero miles de desarrolladores han cometido esos errores miles de veces, y las lecciones y advertencias para evitar esos errores son conocidas y documentadas. Como se ha mencionado aquí: si acepta o rechaza valores NULL, la representación de valores perdidos es un problema resuelto . No es necesario devise una nueva solución solo porque los desarrolladores continúen haciendo errores fáciles de superar (y fáciles de identificar).


Como nota al pie de la página: He sido desarrollador DBE y desarrollador durante más de 20 años (lo que sin duda es suficiente time para que sepa la diferencia entre un ingeniero de bases de datos y un administrador de bases de datos). A lo largo de mi carrera siempre he estado en el campo de "NULLs are useful", aunque era consciente de que varias personas muy inteligentes no estaban de acuerdo. Era extremadamente escéptico sobre el enfoque de "valores especiales", pero no lo suficientemente versado en los estudios académicos de "Cómo evitar NULL de la manera correcta" para tomar una position firme. Siempre me encanta aprender cosas nuevas, y todavía tengo mucho que aprender después de 20 años. Gracias a todos los que contribuyeron para que esta sea una discusión útil.

Saque a su contratista.

De acuerdo, en serio, esto no es una práctica estándar. Esto se puede ver simplemente porque todos los RDBMS con los que he trabajado implementan NULL, lógica para NULL, toman en count NULL en keys externas, tienen un comportamiento diferente para NULL en COUNT, etc., etc.

De hecho, afirmaría que usar 'Z' o cualquier otro marcador de position es peor. Aún necesita código para verificar por 'Z'. Pero también necesitas documentar que 'Z' no significa 'Z', significa algo más. Y debe asegurarse de que se lea dicha documentation. Y luego, ¿qué sucede si 'Z' alguna vez se convierte en una pieza válida de datos? (Como un campo para una inicial?)

En un nivel básico, incluso sin debatir la validez de NULL vs 'Z', insisto en que el contratista cumpla con las prácticas estándar que existen dentro de su empresa, no de él. Instituir su práctica estándar en un entorno con una práctica estándar alternativa causará confusión, gastos generales de mantenimiento, mala comprensión y, al final, mayores costos y errores.


EDITAR

Hay casos en los que usar una alternativa a NULL es válido en mi opinión. Pero solo cuando hacerlo networkinguce el código, en lugar de crear casos especiales que requieren una contabilidad.

Lo he usado para datos vinculados a dates, por ejemplo. Si los datos son válidos entre una date de inicio y una date de finalización, el código se puede simplificar al no tener valores NULOS. En cambio, una date de inicio NULL podría replacese por '01 ene 1900 'y una date de finalización NULL podría replacese por '31 dic 2079'.

Esto aún puede cambiar el comportamiento de lo que se puede esperar, por lo que debe usarse con cuidado:

  • WHERE end-date IS NULL ya no proporciona datos que aún son válidos
  • Acabas de crear tu propio bug del milenio
  • etc.

Esto es equivalente a las abstracciones de reforma de modo que todas las properties siempre puedan tener valores válidos. Es notablemente diferente de la encoding implícita de significado específico en valores elegidos arbitrariamente.

Aún así, saque al contratista.

Esta es fácilmente una de las opiniones más extrañas que he escuchado. El uso de un valor mágico para representar "sin datos" en lugar de NULO significa que cada pieza de código que tenga tendrá que postprocesar los resultados para contabilizar / descartar los valores "sin datos" / "Z".

NULL es especial debido a la forma en que la database lo maneja en las consultas. Por ejemplo, tome estas dos consultas simples:

 select * from mytable where name = 'bob'; select * from mytable where name != 'bob'; 

Si el name alguna vez es NULL, obviamente no aparecerá en los primeros resultados de la consulta. Más importante aún, tampoco aparecerá en los resultados de las segundas consultas. NULL no coincide con otra cosa que no sea una búsqueda explícita de NULL, como en:

 select * from mytable where name is NULL; 

¿Y qué sucede cuando los datos pueden tener Z como un valor válido? Digamos que estás almacenando la inicial del segundo nombre de alguien. ¿Sería Zachary Z Zonkas agrupado con esas personas sin inicial media? ¿O su contratista podría tener otro valor mágico para manejar esto?

Evite los valores mágicos que requieren la implementación de características de la database en un código que la database ya es completamente capaz de manejar. Este es un problema resuelto y bien entendido, y puede ser que su contratista nunca asimilara la noción de NULL y por lo tanto evitara usarlo.

Si el dominio permite valores perdidos, entonces usar NULL para representar 'indefinido' está perfectamente bien (para eso está ahí). El único inconveniente es que el código que consume los datos debe escribirse para verificar los NULL. Esta es la forma en que siempre lo he hecho.

Nunca he escuchado (o visto en la práctica) el uso de 'Z' para representar los datos faltantes. En cuanto a "el contratista cita esto como 'práctica estándar' entre los DBA", ¿puede proporcionar alguna evidencia de esa afirmación? Como @Dems mencionó, también necesita documentar que 'Z' no significa 'Z': ¿qué tal una columna MiddleInitial ?

Al igual que Aaron Alton y muchos otros, creo que los valores NULL son una parte integral del layout de la database, y deben usarse cuando corresponda.

Incluso si de alguna manera logras explicarles a todos tus desarrolladores y DBA actuales y futuros sobre "Z" en lugar de NULL, e incluso si codifican todo a la perfección, aún confundirás el optimizador porque no sabrá que lo has inventado. .

Usar un valor especial para representar NULL (que ya es un valor especial para representar NULL) dará como resultado sesgos en los datos. Por ejemplo, sucedieron muchas cosas el 1 de enero de 1900 que arrojarán la capacidad del optimizador para comprender el range real de dates que realmente son relevantes para su aplicación.

Esto es como si un gerente decidiera: "Usar corbata es malo para la productividad, así que todos vamos a usar cinta adhesiva alnetworkingedor de nuestros cuellos. Problema resuelto".

Nunca escuché sobre el amplio uso de 'Z' como sustituto de NULL .

(Por cierto, no me gustaría especialmente trabajar con un contratista que le dice a primera vista que ellos y otros DBA "avanzados" son mucho más conocedores y mejores que usted).

  +=================================+ | FavoriteLetters | +=================================+ | Person | FavoriteLetter | +--------------+------------------+ | 'Anna' | 'A' | | 'Bob' | 'B' | | 'Clair' | 'C' | | 'Zaphod' | 'Z' | +---------------------------------+ 

¿Cómo interpretaría su contratista los datos de la última fila?

¿Probablemente elegiría un "valor mágico" diferente en esta tabla para evitar la colisión con los datos reales 'Z' ? Lo que significa que tendrías que recordar varios valores mágicos y también cuál se usa donde … ¿cómo es esto mejor que tener solo un token mágico NULL , y tener que recordar las reglas lógicas de tres valores (y las trampas) que lo acompañan? ? NULL al less está estandarizado, a diferencia de la 'Z' su contratista.

No me gusta particularmente NULL tampoco, pero sustituirlo sin pensarlo con un valor real (o peor, con varios valores reales) en todas partes es casi definitivamente peor que NULL .

Permítanme repetir mi comentario anterior aquí para una mejor visibilidad: si quiere leer algo serio y bien fundamentado por personas que están en contra de NULL , recomendaría el breve artículo "Cómo manejar información faltante sin usar NULLs" (enlaces a un PDF) de la página principal de The Third Manifesto ).

Nada en principio requiere valores nulos para el layout correcto de la database. De hecho, hay muchas bases de datos diseñadas sin usar null y hay muchos buenos diseñadores de bases de datos y equipos de desarrollo completos que diseñan bases de datos sin usar valores nulos. En general, es bueno tener cuidado al agregar valores nulos a una database porque inevitablemente conducirán a resultados incorrectos o ambiguos más adelante.

No he oído hablar de usar Z como "práctica estándar" como valor de marcador en lugar de nulos, pero supongo que su contratista se está refiriendo al concepto de valores centinela en general, que a veces se utilizan en el layout de la database. Sin embargo, una forma mucho más común y flexible de evitar nulos sin utilizar datos "ficticios" es simplemente diseñarlos. Descompón la tabla de modo que cada tipo de hecho se registre en una tabla que no tenga attributes "adicionales" no especificados.

En respuesta a los comentarios de los contratistas

  • Cadena vacía <> NULL
  • La secuencia vacía requiere 2 bytes de almacenamiento + una lectura de desplazamiento
  • NULL usa null bitmap = quicker
  • La IDENTIDAD no siempre comienza en 1 (¿por qué perder la mitad de su range?)

Todo el concepto está defectuoso, como la mayoría de las otras respuestas aquí

Aunque nunca he visto 'Z' como un valor mágico para representar nulo, he visto 'X' usado para representar un campo que no se ha rellenado. Dicho esto, solo he visto esto en un solo lugar, y mi interfaz no era una database, sino un file XML … así que no estaría preparado para usar este argumento como una práctica común.

Tenga en count que tenemos que manejar la 'X' especialmente, y, como lo mencionó Dems, tenemos que documentarla, y las personas se han confundido. En nuestra defensa, esto nos lo impone un proveedor externo, ¡no algo que nosotros mismos cocinamos!