Resumen

Diseña estructuras de datos sólidas en MySQL con claves confiables, correos únicos y metadatos que facilitan auditoría y análisis. Aquí se explica cómo crear la tabla clients con auto_increment, validar duplicados con unique, elegir entre timestamp y datetime, usar enum para género y aplicar desactivación lógica con active. Además, se bosqueja la tabla Operations para ventas, préstamos y devoluciones, y cómo finished refleja el estado del flujo.

¿Cómo crear una tabla de clientes robusta en MySQL?

Definimos una estructura clara que prioriza consistencia e integridad. Se parte de un ID en singular, un nombre acotado, un correo único y metadatos de creación y actualización.

CREATE TABLE clients (
  client_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  email VARCHAR(100) NOT NULL UNIQUE,
  birth_date DATETIME NULL,
  gender ENUM('male','female','N/D') NOT NULL,
  active TINYINT(1) NOT NULL DEFAULT 1,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
  • ID con auto_increment: asegura consistencia sin depender de otra capa. Sin auto_increment sigue siendo llave primaria válida, pero otra capa debería asignar el ID.
  • name NOT NULL: máximo 50 caracteres para un nombre corto y obligatorio.
  • email UNIQUE: evita duplicados por correo y permite detectar registros previos antes del insert.
  • gender con enum: sólo permite 'male', 'female' o 'N/D'. Sin default: se debe enviar un valor en cada insert.
  • active TINYINT(1): eliminación lógica. Nunca se borra la tupla; se inactiva con 0 por defecto en 1.
  • created_at y updated_at: metadatos clave para auditoría y análisis.
  • Nota: IF NOT EXISTS es útil, aunque aquí se omitió para simplificar.

¿Qué diferencia hay entre TIMESTAMP y DATETIME y cómo aplicarlos?

Ambos se ven igual al mostrarse (AAAA-MM-DD HH:MM:SS), pero se almacenan distinto.

  • timestamp: basado en epoch (segundos desde 1970-01-01). Es entero, eficiente para cálculos y proyecciones.
  • datetime: representa fechas amplias, incluso anteriores a 1970. Útil para cumpleaños, ya que no todos nacieron después de 1970.
  • Aplicación práctica: birth_date en datetime; metadatos en timestamp por eficiencia.
  • A partir de MySQL 5.3 se puede usar CURRENT_TIMESTAMP en varias columnas con comportamientos distintos.

Ejemplo de metadatos que se actualizan solos:

created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  • Comportamiento: al crear, ambos toman el mismo valor. En un update, sólo updated_at cambia automáticamente.
  • Valor de negocio: permite responder preguntas como “¿cuántos usuarios se crearon la semana pasada?” o “¿cuáles fueron creados el año pasado pero actualizados este año?”.

¿Cómo modelar operaciones de venta, préstamo y devolución?

Se requiere registrar el libro, el cliente y el tipo de operación. Además, finished indica si la operación terminó.

  • type con enum: 'prestado', 'devuelto', 'vendido'.
  • Regla de negocio: 'vendido' implica finished = 1 por defecto. 'prestado' implica finished = 0 hasta que sea 'devuelto' (finished = 1).
  • Incluye metadatos created_at y updated_at como en clients.

Cascarón de la tabla (completar tipos y restricciones):

CREATE TABLE Operations (
  operation_id /* definir tipo y PK */, 
  book_id /* definir tipo */, 
  client_id /* definir tipo */, 
  type /* ENUM('prestado','devuelto','vendido') NOT NULL */, 
  finished /* TINYINT(1) NOT NULL */, 
  created_at /* TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP */, 
  updated_at /* TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP */
);
  • Sugerencia práctica: mantener coherencia de nombres (singular para IDs), usar not null cuando el dato sea obligatorio y centralizar reglas de negocio simples en enum y defaults.

¿Qué le agregarías a Operations para tu caso? Comenta tus decisiones de tipos, restricciones y cómo validarías finished en tus inserts y updates.