Diseño de bases de datos. 3FN

6 comentarios

La Tercera Forma Normal (se abrevia: 3FN) nos dice que para estar en 3FN una tabla debe:

  1. Estar en la 2FN
  2. No tener dependencias transitivas

Se dice que una dependencia es transitiva si una columna depende de otra/s columna/s que no son Primary Key ni de la tabla actual ni de alguna otra tabla.

Ejemplo 1.

Esta tabla no está en la 3FN.

3FN1

Captura 1. Si haces clic en la imagen la verás más grande

3FN2

Captura 2. Si haces clic en la imagen la verás más grande

¿Cuál es el problema? ¿Por qué no está en la 3FN? Porque la columna EMP_TOTALX depende de otras columnas que no son Primary Key, ni de esta tabla ni de alguna otra tabla:

EMP_TOTALX = EMP_SALBAS + EMP_BONIFI – EMP_DESCUE

Como puedes ver, el valor de la columna EMP_TOTALX se halla sumándole al Salario Básico del empleado sus Bonificaciones (o sea el dinero que tiene a su favor) y restándole sus Descuentos (o sea el dinero que tiene en su contra). Por lo tanto no se necesita que exista la columna EMP_TOTALX ya que su valor puede ser fácilmente calculado en un SELECT.

SELECT
   EMP_IDENTI,
   EMP_NOMBRE,
   EMP_APELLD,
   EMP_SALBAS,
   EMP_BONIFI,
   EMP_DESCUE,
   EMP_SALBAS + EMP_BONIFI - EMP_DESCUE AS SALARIO
FROM
   EMPLEADOS

3FN3

Captura 3. Si haces clic en la imagen la verás más grande

Como ves, pudimos calcular el Salario final del Empleado sin necesidad de usar la columna EMP_TOTALX. Eso significa que la columna EMP_TOTALX está de más, está sobrando, es innecesaria, es inútil.

NOTA: Tampoco esta es la manera adecuada para registrar los pagos de sueldos, es solamente un ejemplo para mostrar que la columna EMP_TOTALX no era necesaria y por lo tanto la tabla EMPLEADOS no cumplía con la 3FN.

Ejemplo 2.

Esta tabla no cumple con la 3FN.

3FN4

Captura 4. Si haces clic en la imagen la verás más grande

3FN5

Captura 5. Si haces clic en la imagen la verás más grande

Como puedes ver, esta tabla tampoco cumple con la 3FN. ¿Por qué no? Porque la columna MOV_TOTALX es el resultado de multiplicar el valor de la columna MOV_CANTID por el valor de la columna MOV_PRECIO. Eso implica que la columna MOV_TOTALX es redundante, está sobrando, es innecesaria, es inútil.

Ejemplo 3.

En una tabla se guardan los despachos aduaneros. Uno de los impuestos a pagar es del 2% del total de la mercadería importada. ¿Debemos tener una columna con el importe que corresponde a ese 2%? No, porque el valor de ese impuesto puede ser calculado. ¿Y si el porcentaje del impuesto varía más adelante? Porque sabemos que los gobiernos tienen la mala costumbre de alzar los porcentajes de los impuestos. No importa, porque podemos tener dos tablas para los impuestos: cabecera y detalle.

Impuestos cabecera

Identificador

Nombre del impuesto

Impuestos detalle

Identificador

Identificador de la cabecera

Vigente desde el día

Vigente hasta el día

Porcentaje a pagar

De esta manera, guardamos el “Identificador” del impuesto, no el “Importe” del impuesto. Trabajamos más, sí, es cierto, pero también tenemos nuestras tablas mucho mejor diseñadas e inclusive podemos responder preguntas como ¿ése impuesto cuándo estuvo en vigencia? ¿cuál era el porcentaje de ese impuesto hace 2 años?

Conclusión:

Nunca debes tener en tus tablas columnas que no sean estrictamente necesarias. Si el valor de una columna puede hallarse mediante otras columnas de esa misma fila entonces esa columna está sobrando, está de más, es redundante, es innecesaria, es inútil. Y debes eliminarla para cumplir con la 3FN.

Artículos relacionados:

Consideraciones a tener en cuenta al diseñar una Base de Datos

Diseño de bases de datos. 1FN

Más ejemplos de tablas que no cumplen con la 1FN

Diseño de bases de datos. 2FN

El índice del blog Firebird21

Diseño de bases de datos. 2FN

6 comentarios

La Segunda Forma Normal (se abrevia: 2FN) nos dice que para estar en la 2FN una tabla debe:

  1. Estar en la 1FN
  2. Todas las columnas que no sean parte de la Primary Key deben depender de toda la Primary Key, no solamente de una parte de la Primary Key
  3. Ninguna columna debe depender de otra/s columna/s. Solamente debe depender de la Primary Key y de nada más.

Como vemos, la 2FN depende de la 1FN ya que solamente las tablas que ya están en la 1FN pueden llegar a estar en la 2FN.

Además, si la Primary Key está compuesta por solamente una columna autoincremental, la tabla casi siempre ya está automáticamente en la 2FN.

Es por eso que en mis artículos siempre insisto en que la Primary Key debe estar compuesta por solamente una columna autoincremental. La excepción es cuando necesitarás hacer replicación, en ese caso podría estar compuesta por dos columnas: Código de la Sucursal y Columna autoincremental.

Por lo tanto, mis consejos son:

Si no necesitarás replicación:

La Primary Key debe estar compuesta por solamente una columna autoincremental

Si necesitarás replicación:

La Primary Key puede estar compuesta por dos columnas: CódigoSucursal + ColumnaAutoIncremental

Ejemplo de una tabla que no cumple con la 2FN

2FN1

Captura 1. Si haces clic en la imagen la verás más grande

¿Cuáles son los errores de diseño de esta tabla?

  1. En la columna PRD_NOMPRO se guarda el “Nombre del Proveedor” y en esa columna debería guardarse el “Identificador del Proveedor”. Recuerda que todo lo que puede identificarse mediante una Primary Key debe identificarse con una Primary Key.
  2. En la columna PRD_PAISXX se guarda el país de procedencia del producto pero ese dato debería guardarse en otra tabla. ¿Por qué está mal aquí? porque está dependiendo de la columna PRD_NOMPRO y la columna PRD_NOMPRO no es la Primary Key de esta tabla. Y según la condición 3 de la 2FN (mira arriba, al principio de este artículo) eso no está permitido.

El diseño correcto implica tener 3 tablas:

  1. PROVEEDORES (Identificador, Nombre, etc.)
  2. PRODUCTOS (Identificador, Nombre, etc.)
  3. PRODUCTOS_X_PROVEEDOR(Identificador, Identificador del Proveedor, Identificador del Producto, Precio de Costo, etc.)

En el caso de que los Proveedores nos provean de productos únicos, es decir que ningún Proveedor nos provea el mismo Producto que otro Proveedor entonces necesitaríamos solamente dos tablas: PROVEEDORES y PRODUCTOS, y los datos de la tabla PRODUCTOS_X_PROVEEDOR (Identificador del Proveedor, Precio de Costo, etc.) estarían incluidos en la tabla de PRODUCTOS.

Verificando si todas las tablas están en la 2FN

Cuanto antes verifiques que todas las tablas de tu Base de Datos cumplen con la 2FN, mucho mejor.

Para cada una de las tablas deberás preguntarte:

  • ¿Tiene una Primary Key autoincremental?
  • ¿Hay alguna columna que dependa de otra columna y esa otra columna no es la Primary Key?

Conclusión:

Como habrás notado, cuando normalizamos las tablas trabajamos más, pero en contrapartida nuestro diseño mejora mucho y nos ahorraremos muchísimo trabajo más adelante porque al normalizarlas estamos evitando una gran variedad de problemas. En nuestro ejemplo, supongamos que el Proveedor “LA GRAN CONTINENTAL S.A.” decide mudarse a Chile. Si tenemos nuestras tablas normalizadas entonces ese cambio de país se guarda una sola vez y en una sola tabla. Si no las tenemos normalizadas deberemos guardar el nombre del nuevo país en muchísimas filas de quizás varias tablas, con el riesgo de olvidarnos de alguna y tener así datos inconsistentes.

Por lo tanto, si normalizas tus tablas trabajarás más … pero tarde o temprano valdrá la pena haber hecho ese trabajo.

Artículos relacionados:

Consideraciones a tener en cuenta al diseñar una Base de Datos

Diseño de bases de datos. 1FN

Más ejemplos de tablas que no cumplen con la 1FN

El índice del blog Firebird21