Introducción

Introducción

Se define una tabla de identificación que poseerá los datos principales (especialmente campos únicos). La idea es que una vez almacenados los datos de identificación no puedan modificarse, salvo superusuario.
Se define una tabla relacionada que poseerá los datos secundarios y campos de log.

Si queremos almacenar los datos de una persona definimos dos tablas: id_persona U:M persona. Un usuario ve a la relación como id_persona U:U persona. Siempre ve a la tupla activa.

Ejemplo id_persona

nombres
apellidos
numero_documento

Ejemplo persona

telefono
domicilio
eliminado #Indica si el campo esta activo o no
id_persona FK m:u

¿Por qué utilizar dos tablas y no solamente una con el flag activo?

El problema principal está en las relaciones de la tabla de identificación cuando es una tabla referenciada. Si se utilizara una única tabla, cada vez que hay una reactivación, se deben recorrer las tablas hijas y modificar la clave foránea que apunta a la nueva tupla de identificación.
Utilizando una tabla de identificación, las relaciones con las tablas hijas no varían ante una reactivación.

Implementación

Introducción

* La relación entre persona e id_persona se ve como única: persona.id_persona UNIQUE
* La visualización de persona solo debe mostrar los campos activos.

* La administración de id_persona y persona se realiza conjuntamente o a lo sumo, se administra id_persona solamente.
* Debe modificarse la persistencia de persona, para permitir los logs.
* De forma similiar a la persistencia de persona, debe modificarse la persistencia de todas las entidades (claves foráneas) de persona.

PersonaSql->conditionAux()
//@override Devolver solo los activos
public function conditionAux(){ return "(pers.baja IS NULL) ";  }
PersonaSqlo->deleteByIdSql
//@override Desactivar
public function deleteByIdSql($id){
  $r = $this->formatSql(["id"=>$id ]);
    
  $sql = "
UPDATE " . $this->entity->getSchema_() . $this->entity->getName_() . "
SET pers.baja = now() WHERE id = " . $r["id"] . ";
";
  return ["id"=>$id, "sql"=>$sql];
}
PersonaSqlo->persistSql($row)
//@override Implementar log de relaciones u:m
public function persistSql(array $data) {
  
  if(empty($data["id_persona"])) throw new Exception("Dato obligatorio no definido: id_persona");

  $row = $this->row(["id_persona"=>$data["id_persona"]]);
     
  if($row) {     
    $p = new Persona($row); //Utilizamos las clases "Values"
    if($p->equalTo($data)) return ["id" => $data["id"], "sql" => ""];
    $de = $this->deleteByIdSql($row["id"]);
  }
    
  $in = $this->insertSql($data);
  $in["sql"] = $de["sql"] . $in["sql"];
  return $in;
}
DomicilioSqlo->deleteByIdSql($id) //domicilio entidad débil asociada a persona
 //@override Desactivar
  public function deleteByIdSql($id){
    //NO SE EJECUTA NINGUNA ACCION
    return ["id"=>$id, "sql"=>null];
  }
DomicilioSqlo->persistSql(array $row) //domicilio entidad débil asociada a persona
  //@override Entidad débil de log: Si se modifica debe definirse un nuevo valor
  public function persistSql(array $data) {
    
    $id = $this->id($data); //consulta utilizando todos los campos
    if($id) return ["id" => $data["id"], "sql" => ""];

    $data["id"] = null; //Asignar nuevo id!
    return $this->insertSql($data);  
  }

Fortaleza y Debilidad

Introducción

id_persona: Entidad fuerte
persona: Entidad débil para id_persona y fuerte para sus relaciones
Relaciones m:u de persona: Entidades débiles, NO pueden administrarse fuera de persona. Cada vez que se modifique una entidad débil, se generará una nueva entrada en la entidad débil y en la entidad fuerte que posee el log. La entidad débil modificada permanecerá inmutable.

Ejemplo

Persona _u:u domicilio

Es importante que la tabla de domicilio mantenga la restricción “exclusiva” con la tabla persona. Si domicilio está asociada con otra tabla, no deben compartir la misma tupla.

Domicilio, al ser una entidad débil, no debe ser administrada directamente, su administración está asociada obligatoriamente a otra tabla principal, que será la entidad fuerte.

La administración de domicilio se define obligatoriamente desde la entidad persona.
Cada vez que se modifica el domicilio desde la persona, se generará una nueva entrada en domicilio, por lo que se modificará su id, este id será devuelto a persona quien se persistirá generando una nueva entrada en su log.

Implementación

Al persistir domicilio, se debe crear una nueva entrada manteniendo inmutable la anterior.
Ojo, el modelo lo permite, pero no es correcto realizar una persistencia de domicilio independientemente de persona.

Información adicional

Campos de control
La clave foránea identifica una columna o grupo de columnas en una tabla (tabla hija o referendo) que se refiere a una columna o grupo de columnas en otra tabla (tabla maestra o referenciada).
Modelo entidad-relación
Clave Foránea
Foreign Key