Me topé con un problema de diseño de base de datos que está fuera de mi alcance, y mi gurú de DBA está en simulacros de incendio.
En esencia, tengo una tabla con la siguiente clave primaria (PK por brevedad):
child_id integer
parent_id integer
date datetime
child_id
y parent_id
son claves foráneas para las tablas de entidad. La tabla "secundaria" en sí también contiene una clave foránea para la tabla "principal", y he aquí, cada una child_id
siempre hace referencia a la misma parent_id
que la tabla anterior. De hecho, resulta que hay un código adicional que mantiene los dos sincronizados.
Lo que hace que este principiante de normalización demasiado entusiasta diga "¡Debería eliminar la redundancia en su lugar!"
Me descompongo a lo siguiente:
Table_1 PK:
child_id integer
date datetime
Table_2 PK:
parent_id integer
date datetime
Table_3: (already exists)
child_id integer PRIMARY KEY
parent_id integer FOREIGN KEY
Y he aquí, cuando me uno a estos tipos juntos de forma natural, recupero la tabla original. Es mi entendimiento lo que hace que este 5NF.
Sin embargo, ahora me doy cuenta de que hay una regla comercial oculta.
Normalmente, las fechas asociadas con un determinado child_id
deben ser un subconjunto de las fechas asociadas con el correspondiente parent_id
. Puede ver que la primera tabla impone esta regla.
Mi descomposición no impone la regla, porque puede agregarla libremente a la Tabla 1 hasta que las fechas sean demasiado grandes.
Lo que me lleva aquí, con las siguientes preguntas:
¿Es esta descomposición 5NF? Si bien diría que permite anomalías de inserción, también parece seguir el ejemplo de Wiki, que en sí mismo sigue esta guía . La frase (énfasis mío) "podemos reconstruir todos los hechos verdaderos a partir de una forma normalizada que consta de tres tipos de registros separados" me da una pausa especial, ya que no importa la cantidad de basura que bombeo
Table_1
, la unión natural todavía lo ignora.Supongamos que no me gusta esta descomposición (no me gusta). Reconozco libremente que la solución práctica es dejar la tabla y el código como están. Pero, en teoría, ¿hay alguna forma de descomponer y / o agregar restricciones de manera que me salga de la primera tabla y conserve mis reglas comerciales?
Respuestas:
La normalización se basa en dependencias funcionales. Las dependencias funcionales tienen que ver con la semántica; tienen que ver con lo que significan los datos . Cuando simplifica un problema del mundo real al nivel de "parent_id, child_id, date", y no incluye ningún dato de muestra, realmente limita la cantidad de ayuda que un diseñador de bases de datos puede brindarle.
El hecho de que tenga una clave {child_id, parent_id, date} en una tabla y que tenga (parece) un par único {child_id, parent_id} en la tabla secundaria no significa necesariamente que parte de la combinación sea redundante . Puede significar que en la tabla que tiene {child_id, parent_id, date} como la clave principal, el par de atributos {child_id, parent_id} debería hacer referencia a la tabla secundaria en primer lugar.
Si ese es el caso, puede usar
FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id)
. Para hacer eso, necesita una restricción ÚNICA en el par de columnas (child_id, parent_id) en la tabla "child", que no debería ser un problema si child_id es su clave principal.Pero no hay forma de saberlo sin saber qué significan los datos, y usted es el único en este hilo que lo sabe. (Pero nos complacerá que nos lo explique).
En lo que respecta a la tabla original, parece que estás diciendo que child_id -> parent_id. Si ese es el caso, ¿por qué es parent_id en la tabla original en primer lugar? ¿Por qué la clave no es solo (child_id, date), con una referencia de clave externa a la tabla "child"? Me parece que el tipo de redundancia de la que estás hablando podría resolverse soltando la columna "parent_id".
SQL DDL y datos de muestra en forma de instrucciones INSERT nos ayudan a ayudarlo. Las declaraciones DDL e INSERT son más precisas que las descripciones.
fuente
Prueba esto...
(child_id,parent_id)
en la tabla secundaria(PK,FK:child_id, PK,FK:parent_id, PK:date)
permanece como está, el FK está en 2 columnas a la nueva restricción únicao
(PK,FK:child_id, FK:parent_id)
que sea 1: 1 con hijo(PK,FK: child_id, PK,FK: parent_id, PK:date)
permanece como está. pero el FK está en 2 columnas a la nueva tablaSi nada más, puede inspirarte ...
Si lo he entendido correctamente, eliminará la redundancia y el código ...
fuente