bd-cms-bueno

 Sí. Para el diseño que acabamos de definir, no vamos a agregar entrada_id a subtemas. La relación será:

temas
  ↓
subtemas
  ↓
entradas

Y UNIQUE (subtema_id) garantizará que cada subtema tenga como máximo una entrada.

Te dejo el script completo listo para copiar. También agregué DROP DATABASE IF EXISTS al principio para que puedas eliminar la versión anterior y crearla nuevamente desde cero.

-- ============================================================
-- BASE DE DATOS: BLOG EDUCATIVO
-- ============================================================

DROP DATABASE IF EXISTS blog_educativo;

CREATE DATABASE blog_educativo
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

USE blog_educativo;


-- ============================================================
-- 1. TABLA: TEMAS
-- ============================================================

CREATE TABLE temas (

    id INT AUTO_INCREMENT PRIMARY KEY,

    nombre VARCHAR(150) NOT NULL,

    slug VARCHAR(180) NOT NULL UNIQUE,

    descripcion TEXT,

    activo TINYINT(1) NOT NULL DEFAULT 1,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 2. TABLA: SUBTEMAS
-- ============================================================

CREATE TABLE subtemas (

    id INT AUTO_INCREMENT PRIMARY KEY,

    tema_id INT NOT NULL,

    nombre VARCHAR(150) NOT NULL,

    slug VARCHAR(180) NOT NULL,

    descripcion TEXT,

    activo TINYINT(1) NOT NULL DEFAULT 1,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT fk_subtemas_tema

        FOREIGN KEY (tema_id)

        REFERENCES temas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE,

    UNIQUE KEY uk_subtema_slug (
        tema_id,
        slug
    )

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 3. TABLA: ENTRADAS
-- ============================================================

CREATE TABLE entradas (

    id INT AUTO_INCREMENT PRIMARY KEY,

    tema_id INT NOT NULL,

    subtema_id INT NOT NULL,

    titulo VARCHAR(255) NOT NULL,

    subtitulo VARCHAR(255),

    slug VARCHAR(255) NOT NULL UNIQUE,

    contenido LONGTEXT NOT NULL,

    estado ENUM(
        'borrador',
        'publicado'
    ) NOT NULL DEFAULT 'borrador',

    tipo_recurso ENUM(
        'ninguno',
        'p5'
    ) NOT NULL DEFAULT 'ninguno',

    recurso_ruta VARCHAR(500),

    fecha_publicacion DATETIME NULL,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    fecha_actualizacion TIMESTAMP
        DEFAULT CURRENT_TIMESTAMP
        ON UPDATE CURRENT_TIMESTAMP,


    -- Relación con temas
    CONSTRAINT fk_entradas_tema

        FOREIGN KEY (tema_id)

        REFERENCES temas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE,


    -- Relación con subtemas
    CONSTRAINT fk_entradas_subtema

        FOREIGN KEY (subtema_id)

        REFERENCES subtemas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE,


    -- Un subtema solamente puede tener UNA entrada
    UNIQUE KEY uk_entrada_subtema (
        subtema_id
    )

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 4. TABLA: PREGUNTAS
-- ============================================================

CREATE TABLE preguntas (

    id INT AUTO_INCREMENT PRIMARY KEY,

    tema_id INT NOT NULL,

    subtema_id INT NOT NULL,

    pregunta TEXT NOT NULL,

    explicacion TEXT,

    activo TINYINT(1) NOT NULL DEFAULT 1,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,


    CONSTRAINT fk_preguntas_tema

        FOREIGN KEY (tema_id)

        REFERENCES temas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE,


    CONSTRAINT fk_preguntas_subtema

        FOREIGN KEY (subtema_id)

        REFERENCES subtemas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 5. TABLA: RESPUESTAS
-- ============================================================

CREATE TABLE respuestas (

    id INT AUTO_INCREMENT PRIMARY KEY,

    pregunta_id INT NOT NULL,

    respuesta TEXT NOT NULL,

    es_correcta TINYINT(1) NOT NULL DEFAULT 0,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,


    CONSTRAINT fk_respuestas_pregunta

        FOREIGN KEY (pregunta_id)

        REFERENCES preguntas(id)

        ON DELETE CASCADE

        ON UPDATE CASCADE

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 6. TABLA: FLASHCARDS
-- ============================================================

CREATE TABLE flashcards (

    id INT AUTO_INCREMENT PRIMARY KEY,

    tema_id INT NOT NULL,

    subtema_id INT NOT NULL,

    pregunta TEXT NOT NULL,

    respuesta TEXT NOT NULL,

    imagen VARCHAR(500),

    activo TINYINT(1) NOT NULL DEFAULT 1,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,


    CONSTRAINT fk_flashcards_tema

        FOREIGN KEY (tema_id)

        REFERENCES temas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE,


    CONSTRAINT fk_flashcards_subtema

        FOREIGN KEY (subtema_id)

        REFERENCES subtemas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 7. TABLA: QUIZ VISUAL
-- ============================================================

CREATE TABLE quiz_visual (

    id INT AUTO_INCREMENT PRIMARY KEY,

    tema_id INT NOT NULL,

    subtema_id INT NOT NULL,

    pregunta TEXT NOT NULL,

    imagen VARCHAR(500) NOT NULL,

    explicacion TEXT,

    activo TINYINT(1) NOT NULL DEFAULT 1,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,


    CONSTRAINT fk_quiz_visual_tema

        FOREIGN KEY (tema_id)

        REFERENCES temas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE,


    CONSTRAINT fk_quiz_visual_subtema

        FOREIGN KEY (subtema_id)

        REFERENCES subtemas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 8. TABLA: MEMORAMA
-- ============================================================

CREATE TABLE memorama (

    id INT AUTO_INCREMENT PRIMARY KEY,

    tema_id INT NOT NULL,

    subtema_id INT NOT NULL,

    titulo VARCHAR(255) NOT NULL,

    descripcion TEXT,

    activo TINYINT(1) NOT NULL DEFAULT 1,

    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,


    CONSTRAINT fk_memorama_tema

        FOREIGN KEY (tema_id)

        REFERENCES temas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE,


    CONSTRAINT fk_memorama_subtema

        FOREIGN KEY (subtema_id)

        REFERENCES subtemas(id)

        ON DELETE RESTRICT

        ON UPDATE CASCADE

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 9. TABLA: CARTAS DEL MEMORAMA
-- ============================================================

CREATE TABLE memorama_cartas (

    id INT AUTO_INCREMENT PRIMARY KEY,

    memorama_id INT NOT NULL,

    imagen VARCHAR(500) NOT NULL,

    pareja INT NOT NULL,


    CONSTRAINT fk_memorama_cartas_memorama

        FOREIGN KEY (memorama_id)

        REFERENCES memorama(id)

        ON DELETE CASCADE

        ON UPDATE CASCADE

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 10. BIBLIOTECA: LIBROS
-- ============================================================

CREATE TABLE libros (

    id INT AUTO_INCREMENT PRIMARY KEY,

    titulo VARCHAR(255) NOT NULL,

    subtitulo VARCHAR(255),

    descripcion TEXT,

    fecha DATE,

    archivo VARCHAR(500),

    ruta VARCHAR(500),

    fecha_subida TIMESTAMP DEFAULT CURRENT_TIMESTAMP

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 11. BIBLIOTECA: IMÁGENES
-- ============================================================

CREATE TABLE imagenes (

    id INT AUTO_INCREMENT PRIMARY KEY,

    titulo VARCHAR(255) NOT NULL,

    subtitulo VARCHAR(255),

    descripcion TEXT,

    fecha DATE,

    archivo VARCHAR(500),

    ruta VARCHAR(500),

    fecha_subida TIMESTAMP DEFAULT CURRENT_TIMESTAMP

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- 12. BIBLIOTECA: VIDEOS
-- ============================================================

CREATE TABLE videos (

    id INT AUTO_INCREMENT PRIMARY KEY,

    titulo VARCHAR(255) NOT NULL,

    subtitulo VARCHAR(255),

    descripcion TEXT,

    fecha DATE,

    archivo VARCHAR(500),

    ruta VARCHAR(500),

    plataforma VARCHAR(50),

    fecha_subida TIMESTAMP DEFAULT CURRENT_TIMESTAMP

) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;


-- ============================================================
-- FIN DE LA BASE DE DATOS
-- ============================================================

La modificación clave

De todo el script, lo más importante para lo que estamos aprendiendo es esto:

UNIQUE KEY uk_entrada_subtema (
    subtema_id
)

Eso establece la regla:

SUBTEMA 1 ─────── 1 ENTRADA
SUBTEMA 2 ─────── 1 ENTRADA
SUBTEMA 3 ─────── 1 ENTRADA

Pero permite:

TEMA
 │
 ├── SUBTEMA 1 → ENTRADA 1
 ├── SUBTEMA 2 → ENTRADA 2
 └── SUBTEMA 3 → ENTRADA 3

Y tus tablas de preguntas, flashcards, quiz visual y memorama pueden tener muchas actividades asociadas al mismo subtema, que es diferente de las entradas.

Por ejemplo:

JavaScript
│
└── Funciones
    │
    ├── 1 entrada/tutorial
    │
    ├── 5 preguntas
    │
    ├── 10 flashcards
    │
    ├── 1 quiz visual
    │
    └── 1 memorama

Eso encaja muy bien con la idea de tu sitio educativo.

Comentarios

Entradas más populares de este blog

PROMPT MAESTRO — PLATAFORMA EDUCATIVA PHP + MYSQL

bd-2

La Estructura que Simula una Base de Datos en PHP