2010-01-07 14 views
5

tengo las siguientes tablas:El uso de valores nulos en las tablas relacionadas con restricciones de clave externa

Cateogories

  • CategoryID (int) de clave principal
  • CategoryName (varchar)

Artículos

  • Ite MID (int) de clave principal
  • CategoryID (int)
  • NombreDeElemento (varchar)

Hay una restricción de clave externa en Items.CategoryID. Existe la posibilidad de que cuando se crea un nuevo elemento no haya ninguna categoría asignada.

¿Es mejor establecer Items.CategoryID para permitir nulos y tratar con los nulos en mi código O mejor no permitir nulos, establecer el ID de categoría predeterminado en 1 y crear un registro ficticio en la tabla Categorías llamado "Sin categoría" y luego tratar con esa categoría ficticia en mi código?

+0

Debería haber publicado originalmente que un artículo solo puede estar en una sola categoría. – jpshook

+0

Relacionado: http://stackoverflow.com/questions/2016730/column-nullability-optionality-null-vs-not-null –

Respuesta

6

La forma lógicamente correcta sería que la columna CategoryID fuera NULL cuando no hay una Categoría para el artículo.

Si queda atrapado por cualquiera de los errores asociados con el uso de NULL, entonces es muy probable que sea una señal de que el diseño no ha tenido en cuenta el hecho de que los elementos no pueden tener una categoría. Arregla el diseño El NULL se asegurará de que te limites a resolver el problema correcto.

+0

Un artículo en este contexto siempre tendrá una categoría incluso si esa categoría es "Miscelánea" o similar. NULL solo debe usarse cuando un campo tiene la posibilidad lógica de un estado sin datos, p. fecha de fallecimiento para una persona que aún está viva. – melkisadek

+1

El cartel dice que hay veces en que un artículo no tiene categoría. Eso es diferente de tener una categoría ficticia miscelánea u otra. ¿Tiene alguna información que yo no? –

+1

Una razón más para permitir valores NULL para ninguna categoría: si tiene listas desplegables de categorías, los usuarios terminarán viendo esta categoría ficticia allí a menos que haga un código para excluirla de los menús desplegables, lo que requiere una codificación especial de todos modos. –

0

SQL NULLs are tricky, así que creo que estás mejor con una categoría centinela.

+0

Casi cada viñeta en esa lista es fácil de explicar matemáticamente y ** se explica ** en la especificación SQL. Este es un sitio para responder preguntas, sin publicar quejas acerca de cómo las especificaciones de los estándares no funcionan exactamente de la manera que usted cree que deberían. – Aaronaught

+0

No es necesario quejarse del estándar, un estándar muy útil en general, pero es justo decir que algunas partes del mismo deben evitarse. "Fácil de explicar matemáticamente", esta parte no lo es. – Tobu

+1

La especificación ANSI de NULL es inconsistente y se considera que está rota. La mayoría de los desarrolladores que creen que entienden NULL realmente no lo hacen. – KenFar

0

En este caso, creo que es realmente una cuestión de preferencia personal. De cualquier forma, tendrá que ocuparse de los elementos no clasificados en su código.

1

Lo ideal es forzar una elección de categoría antes de permitir la creación de un artículo. Si un elemento no tendrá categoría en algún momento en el futuro, deberá crear una categoría específica para lidiar con eso. Personalmente, no lo llamaría "sin categoría", ya que esto implica que un usuario puede perseguirlo más tarde, ¡lo cual se olvidará de hacer con alarmante regularidad!

Ve por consistencia lógica o terminarás en un lío. Si eso significa crear una categoría "Varios", haga eso y asegúrese de que (a) los usuarios saben cuándo usarla y (b) se informa periódicamente para asegurarse de que los artículos se categoricen correctamente.

2

Depende:

Si sus artículos realmente no tienen ninguna categoría, entonces le permitirá NULL s, ya que es lo que tienes: no CategoryId.

Si desea mostrar todas las categorías, no desea mostrar la fila ficticia, por lo que tendría que ignorar eso.

Si desea mostrar todos los artículos y mostrar las categorías, es mejor que tenga en cuenta que hay artículos sin categoría, por lo que utilizaría un LEFT JOIN en ese caso.

Si es posible, cambie su aplicación para seleccionar una categoría antes de guardar realmente su artículo.


Si usted quiere tratar de que Uncategorized categoría al igual que las otras categorías (lista de ellos con las otras categorías, contar con los elementos asignados a ella, seleccionarla en listas/menús desplegables), entonces se debe obtener su propia categoría, y Item.CategoryId debe ser NOT NULL.

0

No creo que ninguna de las alternativas sea muy buena.

Si elige el enfoque NULL, tendrá problemas con las complicaciones involucradas en el trabajo con NULLs. Si elige no permitir valores nulos, tendrá que manejar casos en los que, si elimina una categoría, el elemento se cascada.

IMO el mejor diseño es tener tres tablas.

Categories 
ID 
Name 

Items 
ID 
Name 

Categories2Items 
CategoryID 
ItemID 

Esto elimina la necesidad de NULL (y las trampas involucrados), así como le permite tener elementos no categorizados, y artículos que pertenecen a varias categorías. Este diseño está también en Forma normal de Boyce-Codd, que es siempre una buena cosa .. en.wikipedia.org/wiki/BCNF

+1

Luego obtienes múltiples categorías por artículo, llámalas etiquetas. Es un buen diseño, pero ¿es eso lo que quiere el OP? – Tobu

+0

Debería haber mencionado que en este caso era uno a uno para los artículos de las categorías. Su respuesta es apropiada para una situación de muchos a muchos. Para uno a uno, esto complica el SQL y requiere que aplique el uno a uno en la aplicación (desordenado). Mi diseño original es válido por lo menos 3NF. – jpshook

+0

Sí, lo sé. Pero el diseño es extensible y elimina una cantidad de problemas en ambos diseños. Además, si puedo ser quisquilloso, las categorías no son por definición disjuntas. Sin embargo, si esto no es lo que desea OP, entonces elegir el enfoque NULL es claramente mejor que tener una categoría centinela. La eliminación de una categoría a la que pertenece un elemento requeriría una CASCADA para eliminar el elemento, lo que probablemente no sea una buena opción, desencadena que no todo el soporte DBMS o deje un valor NULL como categoryid. Entonces OP tendría elementos NULL-categorized y Uncategorized en su DB. –

1

Para tablas de búsqueda simples de este tipo es casi siempre mejor para no permitir valores nulos y tener el valor desconocido en su tabla de consulta.

¿Por qué?

  • Porque las especificaciones ANSI NULL son inconsistentes y muy complejas. Tratar con nulos aumenta enormemente la probabilidad de defectos de codificación, y requiere mucho más código para escribir
  • Debido a que pocos desarrolladores realmente entienden cómo funcionan los NULL en todos los escenarios
  • Porque simplifica su modelo y las consultas muy bien. Puede unir las cosas muy bien con combinaciones internas desde cualquier dirección con sql muy simple.

Sin embargo, unas pocas precauciones:

  • es posible que desee más de un valor "ficticio": una para "desconocido" y otra para "no asignado". Por supuesto, NULL agrupa ambos en un único valor, por lo que va por encima de & más allá del estándar mínimo si hace esto.
  • En ocasiones terminará teniendo atributos adicionales que no son clave que deben ser anulables o llevar valores de tipo 'n/a' para las filas ficticias. Para tablas de búsqueda muy desnormalizadas (como dimensiones de almacenamiento) probablemente desee valores nulos para estas columnas porque 'n/a' no funciona bien para marcas de tiempo, cantidades, etc.
  • Si aplica esta técnica a más que solo simples tablas de búsqueda complicará drásticamente su diseño. No hagas eso.
Cuestiones relacionadas