debug_mode=ON

Buscar en

 
 

Herencia en una base de datos relacional

Escrito por gimenete hace 1 años bajo una licencia de Creative Commons Creative Commons License
5489 visitas. Etiquetas: sql, sgbd, bases-de-datos

Voy a suponer que tengo una jerarquía de herencia con tres clases: Persona, Cliente, Empleado. La clase Persona es abstracta y las otras son clases concretas que extienden de la primera. De un Cliente vamos a saber su número de tarjeta de crédito y de un empleado vamos a saber la cuenta bancaria donde se domicilian sus nóminas.

Esta es la clase Persona (Java):

public abstract class Persona {

    private String nif;
    private String nombre;
    private String apellidos;

    /* métodos get y set */
}

La clase Cliente sólo añade un campo más:

public class Cliente extends Persona {

    private String tarjetaCredito;

    /* métodos get y set */
}

Y la clase Empleado:

public class Empleado extends Persona {

    private String domiciliacionBancaria;

    /* métodos get y set */
}

Bien, vamos a ver que tenemos tres estrategias para persistir estas clases en una base de datos relacional:

  • Una tabla por cada clase. Por tanto tres tablas: personas, clientes, empleados.
  • Una tabla por cada clase concreta (no abstracta). Dos tablas: clientes y empleados.
  • Una tabla para la jerarquía de herencia. Una tabla: personas.

Voy a explicar detenidamente cada estrategia.

Una tabla por cada clase

Cada tabla contendrá los campos de cada clase. Los únicos campos que se repetirán serán los relativos a las claves primarias. Estas serían las sentencias para crear las tablas:

CREATE TABLE personas (nif CHAR(9) NOT NULL,
        nombre VARCHAR(50),
        apellidos VARCHAR(50),
        PRIMARY KEY(nif));

CREATE TABLE clientes (nif CHAR(9) NOT NULL,
        tarjeta_credito CHAR(16) NOT NULL,
        PRIMARY KEY(nif));

CREATE TABLE empleados (nif CHAR(9) NOT NULL,
        domiciliacion_bancaria CHAR(20) NOT NULL,
        PRIMARY KEY(nif));

ALTER TABLE clientes ADD FOREIGN KEY (nif) REFERENCES personas (nif);
ALTER TABLE empleados ADD FOREIGN KEY (nif) REFERENCES personas (nif);

Los beneficios de esta estrategia son:

  • En caso de que se añadan campos a la clase Persona, sólo hay que añadir columnas a la tabla personas.
  • Si en ciertas consultas sólo necesitamos los datos comunes de clientes y empleados, sólo necesitamos un SELECT.

Los inconvenientes son:

  • Cuando se inserta un cliente o un empleado, hay que insertar en dos tablas.
  • Cuando se consultan datos de un cliente o un empleado, hay que hacer un JOIN.
  • La integridad referencial (claves foráneas/ajenas) pueden influir en el rendimiento de la base de datos.

Una tabla por cada clase concreta

Con esta estrategia las sentencias para crear las tablas serían las siguientes:

CREATE TABLE clientes (nif CHAR(9) NOT NULL,
        nombre VARCHAR(50),
        apellidos VARCHAR(50),
        tarjeta_credito CHAR(16) NOT NULL,
        PRIMARY KEY(nif));

CREATE TABLE empleados (nif CHAR(9) NOT NULL,
        nombre VARCHAR(50),
        apellidos VARCHAR(50),
        domiciliacion_bancaria CHAR(20) NOT NULL,
        PRIMARY KEY(nif));

Los beneficios de esta estrategia son:

  • Cuando se inserta un cliente o un empleado sólo se actualiza una tabla.
  • Cuando se consultan datos de un cliente o un empleado sólo se consulta una tabla.
  • No hay restricciones referenciales.

Los inconvenientes son:

  • En caso de que se añadan campos a la clase Persona habría que modificar varias tablas.
  • Si en alguna consulta necesitamos datos de clientes y empleados tendríamos que hacer dos SELECT y unir los resultados. O hacer un UNION.

Una tabla para la jerarquía de herencia

Con esta estrategia sólo tendríamos una tabla:

CREATE TABLE personas (nif CHAR(9) NOT NULL,
        nombre VARCHAR(50),
        apellidos VARCHAR(50),
        tipo CHAR(1) NOT NULL,
        tarjeta_credito CHAR(16),
        domiciliacion_bancaria CHAR(20),
        PRIMARY KEY(nif));

He añadido una columna "tipo". Esa columna permitirá saber si el registro se refiere a un cliente o a un empleado. También he eliminado las restricciones "NOT NULL" tanto de la columna tarjetacredito como de la columna domiciliacionbancaria debido a que ahora podrán ser NULL. Si una persona es cliente tendrá domiciliacionbancaria a NULL y viceversa con el campo tarjetacredito si es un empleado.

Los beneficios de esta estrategia son:

  • Cuando se inserta un cliente o un empleado sólo se actualiza una tabla.
  • Cuando se consultan datos de un cliente o un empleado sólo se consulta una tabla.
  • No hay restricciones referenciales.
  • En caso de que se añadan campos a la clase Persona sólo habría que cambiar una tabla.

Los inconvenientes son:

  • Deberemos utilizar características avanzadas de la base de datos si queremos mantener las restricciones NOT NULL de ciertas columnas.

Conclusiones

En conclusión lo más común desde mi experiencia es utilizar la segunda o la tercera estrategias. Elegir entre ellas dependerá de las consultas que se han de hacer a la base de datos. Si por ejemplo en ningún momento hacemos una consulta que involucre tanto a clientes y empleados, quizá lo mejor será tener una tabla por cada clase concreta. Si por el contrario es común hacer listados que involucren a ambas clases, entonces lo mejor será utilizar una sola tabla.

 

¡Votalo! 5 votos
¡Compártelo!

        

&nbps;

&nbps;

gimenete

Sobre gimenete

Gimenete es un tipo al que le encanta programar. Lleva media vida programando en Java, y ahora le da bastante también a Python. No le hace ascos a JavaScript. Su tema de investigación favorito ahora es el cloud computing.

 
Regístrate o haz login para participar.
¿Todavía no conoces debugmodeon?
debugmodeon es la red social para profesionales de la informática
descubre debugmodeon
 

6 comentarios en "Herencia en una base de datos relacional"

nestor.salceda
nestor.salceda escribió
hace 1 años

#1   

Bastante clarito la verdad, conciso y recomendable :)

 

ian_scho
ian_scho escribió
hace 1 años

#2   

La palabra redundancia no parece en el articulo... Pero has ahorrado mucho tiempo de desarrollo usando la tercera estrategia. Bien escrito.

 

ian_scho
ian_scho escribió
hace 1 años

#3   

La palabra redundancia no parece en el articulo... Pero has ahorrado mucho tiempo de desarrollo usando la tercera estrategia. Bien escrito.

 

Pogasu
Pogasu escribió
hace 1 años

#4   

Es un artículo que es muy claro. Ayuda bastante..

 

torhector2
torhector2 escribió
hace 1 años

#5   

¿Sería muy descabellado darle a la columna "tipo" un valor entero y que fuera la clave foranea de una tabla nueva que almacenase los distintos tipos?, por ejemplo:

TABLA TIPOS
++++++++++++++++++++++

INTEGER ID_TIPO (PK)
VARCHAR(50) NOMBRE

Editado 1 veces. La última vez hace hace 1 años.

 

gimenete
gimenete escribió
hace 1 años

#6   

Es una buena idea para validar el tipo usando restricción referencial.

 
 
 
 

© Copyright 2008-2009 debug_mode=ON | Aviso legal | Contacto | FAQ | ¿Quiénes somos? |