En la lección 01-01 usamos palabras como tabla, fila, columna, clave primaria y clave ajena de manera deliberadamente informal: nos servían para diagnosticar la hoja de cálculo de BiblioRed sin tener que definir nada con rigor. Ahora toca hacerlo bien. El modelo relacional no es "una forma bonita de organizar tablas": es una teoría matemática, publicada por Edgar F. Codd en 1970, y esa base formal es exactamente la razón de que los sistemas relacionales lleven medio siglo sin ser desplazados.
Entender el modelo tiene una consecuencia muy práctica. Cuando dentro de dos lecciones escribas un JOIN y no devuelva lo que esperabas, o cuando una comparación con NULL no filtre ninguna fila, la explicación no estará en el manual de PostgreSQL: estará en la teoría que veremos hoy. Esta es la última lección sin teclear (casi: hay SQL de ilustración, pero no lo ejecutarás todavía). Al final tendrás el plano completo del esquema de BiblioRed, que en la lección siguiente convertiremos en tablas reales dentro de biblioredb.
Contenido
- Relación, tupla, atributo y dominio
- Grado y cardinalidad
- Por qué una relación es un conjunto
- Relación frente a hoja de cálculo
- La familia de las claves: superclave, candidata, primaria, alternativa
- Claves ajenas y el vínculo entre relaciones
- Clave natural frente a clave subrogada: el caso del ISBN
- Las tres reglas de integridad del modelo
- El valor
NULLy la lógica de tres valores - Introducción al álgebra relacional
- El esquema conceptual de BiblioRed
- Errores comunes y consejos
- Ejercicios
- Conclusión
- Relación, tupla, atributo y dominio
El modelo relacional se construye sobre cuatro conceptos. Los presentamos con su nombre formal y con su nombre coloquial, porque en el trabajo diario oirás los dos.
| Nombre formal | Nombre coloquial (SQL) | Qué es |
|---|---|---|
| Relación | Tabla | Un conjunto de tuplas que comparten la misma estructura |
| Tupla | Fila o registro | Un elemento de la relación: los datos de un socio, un libro |
| Atributo | Columna o campo | Una propiedad con nombre, presente en todas las tuplas |
| Dominio | Tipo de dato | El conjunto de valores válidos para un atributo |
Cuidado con una confusión muy extendida: "relación" no significa "vínculo entre tablas". En el modelo relacional, una relación es una tabla. El vínculo entre tablas se llama clave ajena (o, en diseño, interrelación). Que el modelo se llame "relacional" no viene de que las tablas se relacionen entre sí, sino de que cada tabla es, matemáticamente, una relación en el sentido de la teoría de conjuntos: un subconjunto del producto cartesiano de sus dominios.
Veámoslo con la relación socios de BiblioRed:
| socio_id | nombre | apellidos | fecha_alta | sucursal_id | |
|---|---|---|---|---|---|
| 14 | Marta | Alsina | [email protected] | 2021-03-08 | 2 |
| 15 | Iván | Pereda | [email protected] | 2021-09-19 | 2 |
| 16 | Nuria | Bastos | [email protected] | 2022-01-30 | 1 |
- La relación es
socios. - Cada una de las tres líneas es una tupla.
nombre,email,fecha_alta… son atributos.- El dominio de
fecha_altaes "las fechas válidas del calendario"; el desocio_id, "los enteros positivos"; el deemail, "cadenas de hasta 120 caracteres". El dominio es lo que impide que enfecha_altaaparezca"el martes pasado".
Esquema e instancia, otra vez
En 01-01 distinguimos esquema (la estructura) de instancia (los datos de un momento concreto). Formalmente:
- El esquema de la relación se escribe
socios(socio_id, nombre, apellidos, email, fecha_alta, sucursal_id). Es estable: cambia solo cuando el diseñador lo cambia. - La instancia o extensión es el conjunto concreto de tuplas que hay ahora mismo. Cambia con cada préstamo, cada alta y cada baja.
Cuando hablamos de "la tabla socios" casi siempre nos referimos al esquema; cuando decimos "hay 12.000 socios", a la instancia.
- Grado y cardinalidad
Dos medidas elementales de una relación:
- Grado (o aridad): el número de atributos. La relación
sociosdel ejemplo tiene grado 6. El grado es una propiedad del esquema. - Cardinalidad: el número de tuplas. En el ejemplo, 3; en BiblioRed de verdad, 12.000. La cardinalidad es una propiedad de la instancia.
Una regla mnemotécnica: el grado se cuenta a lo ancho y casi nunca cambia; la cardinalidad se cuenta a lo alto y cambia todo el rato.
Casos límite que conviene tener claros:
- Una relación de cardinalidad 0 (sin tuplas) es perfectamente válida: es exactamente lo que tenemos ahora en
biblioredb, donde las tablas ni siquiera existen todavía, y lo que tendremos tras crearlas en la lección siguiente. - Una relación de grado 0 es una curiosidad matemática sin utilidad práctica; SQL no la admite.
- Por qué una relación es un conjunto
Aquí está la idea que más consecuencias tiene. Una relación es un conjunto de tuplas, y los conjuntos matemáticos tienen dos propiedades que las hojas de cálculo no tienen:
No hay orden
En un conjunto, {a, b, c} y {c, a, b} son el mismo conjunto. Por tanto, las filas de una tabla no tienen orden intrínseco. Tampoco lo tienen las columnas, aunque en SQL se declaran en una secuencia.
La consecuencia práctica es contundente: si ejecutas una consulta sin ORDER BY, el gestor puede devolverte las filas en cualquier orden, y ese orden puede cambiar entre dos ejecuciones idénticas sin que nadie haya tocado nada. No es un fallo: es el modelo. Si el orden importa, hay que pedirlo explícitamente (lo veremos en 02-03).
No hay duplicados
En un conjunto, un elemento está o no está; no puede estar "dos veces". Por tanto, en una relación no puede haber dos tuplas idénticas. Esta propiedad es la que justifica la existencia obligatoria de una clave primaria: siempre debe haber algo que distinga una tupla de otra.
La letra pequeña: SQL no es tan estricto
Honestidad intelectual: SQL no implementa el modelo relacional puro. Una tabla SQL es técnicamente un multiconjunto (bag), no un conjunto: si no declaras una clave primaria ni una restricción de unicidad, SQL te dejará insertar dos filas idénticas y ambas convivirán.
-- Legal en SQL si la tabla no tiene clave primaria.
-- Prohibido en el modelo relacional puro.
INSERT INTO socios_sin_clave VALUES ('Marta', 'Alsina');
INSERT INTO socios_sin_clave VALUES ('Marta', 'Alsina');
-- Resultado: dos filas indistinguibles, imposibles de borrar por separadoPor eso una de las primeras reglas prácticas del curso es: toda tabla lleva clave primaria. No es burocracia; es lo que devuelve a la tabla su condición de relación.
- Relación frente a hoja de cálculo
La hoja de cálculo de BiblioRed que diagnosticamos en 01-01 se parecía mucho a una tabla. Estas son las diferencias que la hacían fallar:
| Aspecto | Relación (modelo relacional) | Hoja de cálculo |
|---|---|---|
| Orden de las filas | No existe; se pide con ORDER BY |
Es intrínseco: la fila 7 está entre la 6 y la 8 |
| Duplicados | Prohibidos (clave primaria) | Permitidos y frecuentes |
| Dominio de una columna | Fijo y verificado por el gestor | Cada celda puede tener el tipo que quiera |
| Celdas vacías | NULL, con semántica definida |
Vacío ambiguo: ¿cero, texto vacío, no aplica? |
| Identificación de una fila | Por el valor de su clave | Por su posición (A7) |
| Referencias entre datos | Claves ajenas verificadas | Fórmulas frágiles que se rompen al insertar filas |
| Acceso simultáneo | Controlado por el gestor | Un usuario a la vez, o conflictos de versión |
La diferencia decisiva es la penúltima línea. En una hoja de cálculo, una fila se identifica por dónde está; en una relación, por lo que vale. Por eso insertar una fila en medio de una hoja rompe fórmulas, y por eso en una base de datos no rompe nada: nadie depende de la posición.
- La familia de las claves: superclave, candidata, primaria, alternativa
Para garantizar que no hay tuplas duplicadas necesitamos identificar cada tupla. El modelo define una jerarquía precisa de conceptos. Trabajaremos sobre la relación libros de BiblioRed:
| libro_id | isbn | titulo | autor_id | editorial | anio_publicacion |
|---|---|---|---|---|---|
| 331 | 9788401339097 | El mapa del tiempo | 1 | Editorial Andana | 2008 |
| 332 | 9788401337208 | Los pilares de la Tierra | 2 | Editorial Andana | 1989 |
| 333 | 9788412007701 | La casa de las mareas | 3 | Ediciones Marlia | 2015 |
Superclave
Un conjunto de atributos que identifica unívocamente cada tupla: no puede haber dos tuplas con los mismos valores en todos ellos.
En libros son superclaves, entre otras:
{libro_id}{isbn}{libro_id, titulo}{isbn, editorial, anio_publicacion}- El conjunto de todos los atributos (siempre es superclave, porque no hay tuplas duplicadas)
Fíjate en que a una superclave le puedes añadir atributos irrelevantes y sigue siendo superclave. Por eso hace falta afinar.
Clave candidata
Una superclave mínima: si le quitas cualquier atributo, deja de identificar unívocamente. {libro_id, titulo} no es candidata, porque {libro_id} ya basta por sí solo. En libros las claves candidatas son:
{libro_id}{isbn}
Una relación puede tener varias claves candidatas, y siempre tiene al menos una.
Clave primaria
La clave candidata que el diseñador elige como identificador oficial. Es la que usarán las claves ajenas de otras tablas y la que el gestor emplea para organizar el almacenamiento. En libros elegiremos libro_id (en el apartado 7 justificamos por qué).
Clave alternativa
Las claves candidatas no elegidas. En libros, isbn es clave alternativa. En SQL se declaran con UNIQUE, y siguen siendo tan obligatorias de respetar como la primaria: si dejas que dos libros compartan ISBN, el catálogo de BiblioRed se corrompe igual.
Clave compuesta
Una clave (candidata o primaria) formada por más de un atributo. Si BiblioRed tuviera una tabla libros_autores para libros escritos a varias manos, su clave primaria natural sería {libro_id, autor_id}: ni el libro solo ni el autor solo bastan, pero la pareja sí.
flowchart TD
A["Todos los conjuntos de atributos"] --> B["Superclaves<br/>identifican unívocamente"]
B --> C["Claves candidatas<br/>superclaves mínimas"]
C --> D["Clave primaria<br/>la candidata elegida"]
C --> E["Claves alternativas<br/>las candidatas no elegidas<br/>(UNIQUE en SQL)"]
- Claves ajenas y el vínculo entre relaciones
Una clave ajena (foreign key) es un atributo, o conjunto de atributos, de una relación cuyos valores deben coincidir con los de la clave primaria de otra relación (o de la misma).
En BiblioRed:
socios.sucursal_ides clave ajena haciasucursales.sucursal_id: cada socio pertenece a una sucursal existente.ejemplares.libro_ides clave ajena hacialibros.libro_id: cada ejemplar físico es una copia de un libro del catálogo.prestamos.socio_idyprestamos.ejemplar_idson dos claves ajenas en la misma tabla: un préstamo conecta un socio con un ejemplar.
Vocabulario: la tabla que contiene la clave ajena es la hija o referenciante; la que contiene la clave primaria apuntada es la padre o referenciada.
Dos observaciones importantes:
- Una clave ajena puede admitir
NULL(salvo que se declareNOT NULL), y eseNULLsignifica "esta fila no apunta a nadie". Si permitiéramosejemplares.sucursal_idnulo, estaríamos diciendo que hay ejemplares sin sucursal asignada. En BiblioRed no queremos eso, así que seráNOT NULL. - Una clave ajena puede repetirse. Que
sucursal_idvalga 2 en cientos de socios es exactamente lo esperado: es una relación uno-a-muchos.
El tratamiento práctico de las claves ajenas —qué pasa cuando borras la fila padre, ON DELETE CASCADE, RESTRICT, restricciones diferibles— es el contenido completo de la lección 02-06. Aquí nos quedamos en el concepto.
- Clave natural frente a clave subrogada: el caso del ISBN
Este es un debate real de diseño, y BiblioRed lo tiene delante.
- Una clave natural es un identificador que ya existe en el mundo real y que hemos adoptado como clave: el ISBN de un libro, el NIF de una persona, el código IATA de un aeropuerto.
- Una clave subrogada (o artificial) es un número que inventa la propia base de datos, sin significado fuera de ella:
libro_id = 331.
¿Debería libros tener como clave primaria el isbn (natural) o un libro_id (subrogada)? Comparemos:
| Criterio | Clave natural (isbn) |
Clave subrogada (libro_id) |
|---|---|---|
| Significado | Tiene sentido fuera de la BD | Ninguno; solo sirve dentro |
| Estabilidad | Puede cambiar o corregirse (ISBN-10 → ISBN-13, erratas de catalogación) | Nunca cambia |
| Tamaño | 13 caracteres, replicados en cada clave ajena | 4 bytes de entero |
| Legibilidad al depurar | Alta: ves el ISBN y sabes qué libro es | Baja: 331 no dice nada |
| Universalidad | No todos los ítems lo tienen: revistas, folletos, donaciones antiguas | Siempre existe |
| Riesgo de duplicados | Real: reediciones mal catalogadas comparten ISBN por error | Nulo |
Decisión para BiblioRed: clave primaria subrogada libro_id, y isbn como clave alternativa UNIQUE. Los tres motivos que pesan más:
- No todo lo que presta BiblioRed tiene ISBN. Fondos anteriores a 1970, publicaciones municipales y donaciones sin catalogar quedarían sin clave. Y una clave primaria no admite
NULL(lo veremos en el apartado siguiente). - El ISBN se corrige. Cuando un bibliotecario detecta que se tecleó mal un ISBN y lo arregla, con clave natural habría que propagar el cambio a todas las tablas hijas; con clave subrogada, se corrige un único valor y nadie más se entera.
- Las claves ajenas se abaratan.
ejemplarestiene 40.000 filas: guardar en cada una un entero de 4 bytes en lugar de una cadena de 13 caracteres reduce el tamaño de la tabla y de sus índices.
Lo que no hacemos es renunciar al ISBN: sigue declarado UNIQUE, de modo que sigue siendo imposible catalogar dos veces el mismo libro. Elegir clave subrogada no es excusa para perder las restricciones del mundo real; ese es el error clásico.
El mismo razonamiento se aplica a ejemplares: la etiqueta física EJ-3081 que lleva pegada el ejemplar es una clave natural excelente para el mostrador, pero la guardaremos en una columna codigo con UNIQUE, y la clave primaria será el entero ejemplar_id.
- Las tres reglas de integridad del modelo
El modelo relacional define tres reglas que todo sistema debe hacer cumplir. Se llaman reglas de integridad porque su función es impedir que la base de datos entre en un estado imposible.
Integridad de dominio
Todo valor de un atributo debe pertenecer a su dominio.
Es la regla más elemental y la que más trabajo ahorra. Si el dominio de fecha_prestamo son las fechas, el gestor rechaza 'ayer', '32/13/2026' y '-1'. Si el dominio de anio_publicacion son los enteros, rechaza 'mil novecientos ochenta y nueve'.
En SQL, la integridad de dominio se expresa con los tipos de datos (los veremos operativamente en 02-02) y se refina con restricciones CHECK y NOT NULL (catálogo completo en 04-04).
En la hoja de cálculo de BiblioRed no había integridad de dominio: por eso convivían 2026-06-02, 02/06/26 y pendiente en la misma columna de fechas.
Integridad de entidad
Ningún atributo de la clave primaria puede ser NULL.
El razonamiento es directo: la clave primaria sirve para identificar la tupla. Si su valor es desconocido, la tupla no es identificable, y entonces no puede formar parte de una relación (recuerda: sin duplicados, y dos tuplas con clave desconocida no se pueden distinguir).
De aquí sale la consecuencia práctica del apartado anterior: como no todos los ítems de BiblioRed tienen ISBN, el ISBN no puede ser clave primaria, porque tendría que admitir NULL.
En SQL, esta regla es automática: declarar PRIMARY KEY implica NOT NULL aunque no lo escribas.
Integridad referencial
Todo valor no nulo de una clave ajena debe corresponderse con un valor existente de la clave primaria referenciada.
Enunciada así de simple, prohíbe las filas huérfanas: un préstamo cuyo socio_id sea 9999 cuando no existe el socio 9999; un ejemplar de un libro que no está en el catálogo. En la hoja de cálculo de BiblioRed las había a montones, porque nada impedía teclear un número de socio inventado.
Cómo se declara, qué comprueba el gestor en cada operación y qué hacer cuando borras la fila padre es el contenido íntegro de la lección 02-06. Aquí basta con retener el enunciado.
- El valor
NULL y la lógica de tres valores
NULL y la lógica de tres valoresNULL no es cero. NULL no es la cadena vacía. NULL no es "falso". NULL es la ausencia de valor, y admite al menos tres lecturas distintas que el modelo no distingue:
- Desconocido: el socio 19, Pau Miralles, tiene correo pero no lo dio al darse de alta.
- No aplicable:
fecha_devolucionde un préstamo todavía abierto — el libro no se ha devuelto, así que no hay fecha que poner. - Pendiente: aún no se ha registrado.
En BiblioRed usaremos fecha_devolucion IS NULL como definición operativa de "préstamo abierto". Es un uso limpio y muy común: la ausencia de fecha significa algo.
La lógica de tres valores
Como NULL significa "no sé", cualquier comparación con NULL da como resultado… no sé. SQL formaliza esto con una lógica de tres valores: VERDADERO, FALSO y DESCONOCIDO.
| Expresión | Resultado |
|---|---|
5 = 5 |
VERDADERO |
5 = 3 |
FALSO |
5 = NULL |
DESCONOCIDO |
NULL = NULL |
DESCONOCIDO |
NULL <> NULL |
DESCONOCIDO |
Sí: NULL = NULL no es verdadero. Y tiene toda la lógica del mundo: si no sé la edad de Marta ni la de Iván, no puedo afirmar que sean iguales.
Tablas de verdad de los operadores lógicos (D = desconocido):
A |
B |
A AND B |
A OR B |
|---|---|---|---|
| V | V | V | V |
| V | F | F | V |
| V | D | D | V |
| F | F | F | F |
| F | D | F | D |
| D | D | D | D |
Dos casillas merecen atención: FALSO AND DESCONOCIDO es FALSO (si una parte ya falla, da igual el resto) y VERDADERO OR DESCONOCIDO es VERDADERO (si una parte ya se cumple, da igual el resto).
La consecuencia que más disgustos causa
Un filtro solo deja pasar las filas para las que la condición es VERDADERO. DESCONOCIDO no pasa. Por eso:
-- MAL: no devuelve NADA, ni siquiera los préstamos abiertos
SELECT * FROM prestamos WHERE fecha_devolucion = NULL;
-- BIEN: el operador correcto para preguntar por la ausencia
SELECT * FROM prestamos WHERE fecha_devolucion IS NULL;La primera consulta no da error de sintaxis —y eso la hace peligrosa—, simplemente devuelve cero filas siempre. Los operadores correctos son IS NULL e IS NOT NULL. Los practicaremos en 02-03.
Una trampa más sutil, y muy real: WHERE estado <> 'prestado' no devuelve las filas cuyo estado sea NULL, porque NULL <> 'prestado' es DESCONOCIDO. Si quieres incluirlas, hay que pedirlo: WHERE estado <> 'prestado' OR estado IS NULL.
- Introducción al álgebra relacional
Codd no se limitó a definir qué es una relación: definió también un álgebra para operar con ellas. La idea es elegante: cada operación toma una o dos relaciones y devuelve otra relación. Al ser cerrado (entra relación, sale relación), se pueden encadenar operaciones indefinidamente, y de ahí nace la posibilidad de consultar.
Aquí solo lo presentamos conceptualmente, sin ejercicios de notación. Lo importante es que veas que cada operación del álgebra tiene su traducción directa en SQL: SQL es la realización práctica del álgebra relacional, y el optimizador que vimos en 01-04 trabaja precisamente reordenando estas operaciones para que cuesten menos.
Selección (σ)
Elige filas que cumplen una condición. El resultado tiene el mismo grado y menor o igual cardinalidad.
"Los ejemplares de la sucursal 2" → σ sucursal_id = 2 (ejemplares)
Proyección (π)
Elige columnas. El resultado tiene menor grado. En el álgebra pura, la proyección elimina duplicados (porque el resultado debe ser un conjunto); en SQL no lo hace salvo que escribas DISTINCT.
"Solo el título y el ISBN de los libros" → π titulo, isbn (libros)
Producto cartesiano (×)
Combina cada tupla de una relación con cada tupla de la otra. Si socios tiene 12.000 filas y libros 8.000, el producto tiene 96.000.000. Rara vez se quiere por sí mismo, pero es el fundamento teórico de todas las combinaciones.
Reunión (⋈, join)
Un producto cartesiano seguido de una selección que empareja las tuplas relacionadas. Es la operación que recompone la información repartida en varias tablas.
"Cada préstamo con los datos de su socio" → prestamos ⋈ prestamos.socio_id = socios.socio_id socios
Es tan central que le dedicamos la lección entera 02-04.
Unión (∪)
Junta las tuplas de dos relaciones compatibles (mismo número de atributos y dominios compatibles) y elimina duplicados.
"Todos los identificadores de socio que aparecen en préstamos o en reservas"
Diferencia (−)
Las tuplas que están en la primera relación y no en la segunda. Es la operación que responde a las preguntas negativas.
"Socios que han reservado pero nunca han tomado nada prestado"
Un mapa de correspondencias
| Operación del álgebra | Símbolo | Cláusula SQL |
|---|---|---|
| Selección | σ | WHERE |
| Proyección | π | lista de columnas del SELECT (+ DISTINCT) |
| Producto cartesiano | × | CROSS JOIN |
| Reunión | ⋈ | JOIN ... ON |
| Unión | ∪ | UNION |
| Diferencia | − | EXCEPT (MINUS en Oracle) |
| Intersección | ∩ | INTERSECT |
| Renombrado | ρ | AS |
Esta tabla es, en la práctica, el índice de las tres lecciones siguientes.
- El esquema conceptual de BiblioRed
Con todo el vocabulario en la mano, este es el plano que construiremos en la lección 02-02. Siete relaciones:
erDiagram
SUCURSALES ||--o{ SOCIOS : "es sucursal de alta de"
SUCURSALES ||--o{ EJEMPLARES : "custodia"
AUTORES ||--o{ LIBROS : "escribe"
LIBROS ||--o{ EJEMPLARES : "tiene copias en"
SOCIOS ||--o{ PRESTAMOS : "realiza"
EJEMPLARES ||--o{ PRESTAMOS : "es objeto de"
SOCIOS ||--o{ RESERVAS : "solicita"
LIBROS ||--o{ RESERVAS : "es objeto de"
SUCURSALES {
int sucursal_id PK
varchar nombre UK
varchar direccion
varchar telefono
date fecha_apertura
}
SOCIOS {
int socio_id PK
varchar nombre
varchar apellidos
varchar email UK
date fecha_alta
int sucursal_id FK
boolean activo
}
AUTORES {
int autor_id PK
varchar nombre
varchar apellidos
varchar nacionalidad
int anio_nacimiento
}
LIBROS {
int libro_id PK
varchar isbn UK
varchar titulo
int autor_id FK
varchar editorial
int anio_publicacion
varchar idioma
}
EJEMPLARES {
int ejemplar_id PK
varchar codigo UK
int libro_id FK
int sucursal_id FK
varchar estado
date fecha_adquisicion
}
PRESTAMOS {
int prestamo_id PK
int socio_id FK
int ejemplar_id FK
date fecha_prestamo
date fecha_devolucion_prevista
date fecha_devolucion
numeric recargo
}
RESERVAS {
int reserva_id PK
int socio_id FK
int libro_id FK
date fecha_reserva
date fecha_expiracion
varchar estado
}
Las decisiones de diseño que ya podemos justificar con lo aprendido:
- Siete claves primarias subrogadas, una por tabla, todas enteras y autogeneradas. Cumplen la integridad de entidad sin depender de datos del mundo real.
libros.isbnyejemplares.codigocomo claves alternativas (UNIQUE): conservamos las restricciones naturales sin convertirlas en clave primaria.- La distinción entre
librosyejemplareses la clave del modelo.libroses la obra (el título, el ISBN, el autor);ejemplareses el objeto físico que se presta y que está en una estantería concreta. BiblioRed tiene unos 8.000 libros distintos y 40.000 ejemplares. Prestar un "libro" no significa nada: se presta un ejemplar. prestamosapunta aejemplares, no alibros, precisamente por lo anterior.reservas, en cambio, apunta alibros: un socio reserva la obra, y ya se le asignará el ejemplar que se libere antes. Esta asimetría no es un descuido, es el modelo del negocio.fecha_devolucionadmiteNULLy eseNULLsignifica "préstamo abierto". Es el uso legítimo del valor nulo que vimos en el apartado 9.recargoesNUMERIC, no coma flotante, porque representa dinero. La justificación completa está en la lección siguiente.
Este esquema no es todavía un diseño terminado: un libro puede tener varios autores, y con libros.autor_id solo cabe uno. Es una simplificación consciente para el módulo 2; las técnicas para modelar bien ese caso (diagramas E-R, relaciones N:M, tablas intermedias) llegan en el módulo 4, y la teoría que dice por qué ciertos diseños degeneran, en el módulo 5.
Errores Comunes y Consejos
- Confundir "relación" con "vínculo entre tablas". Una relación es una tabla. El vínculo es una clave ajena. Es el malentendido número uno del vocabulario relacional.
- Suponer que las filas tienen un orden. "Los últimos préstamos están al final de la tabla" es falso. Sin
ORDER BYno hay orden garantizado, y confiar en el que salga hoy es una avería aplazada. - Diseñar tablas sin clave primaria. SQL lo permite, y por eso hay que imponérselo uno mismo. Sin clave primaria puedes acabar con dos filas idénticas que no se pueden actualizar ni borrar por separado.
- Escribir
= NULLen lugar deIS NULL. No da error: devuelve cero filas en silencio. Es el fallo más caro de esta lección. - Elegir clave natural por comodidad. El ISBN parece perfecto hasta que aparece el primer folleto municipal sin ISBN o la primera errata que hay que corregir en cascada.
- Renunciar al
UNIQUEporque ya hay clave subrogada. Ponerlibro_idno autoriza a permitir dos libros con el mismo ISBN. La clave subrogada identifica; la alternativa protege la realidad. - Usar
NULLcomo comodín polivalente. SiNULLenestadosignifica a veces "no lo sé" y a veces "dado de baja", nadie podrá volver a consultar esa columna con confianza. UnNULL, un significado. - Consejo: cuando una consulta futura te devuelva menos filas de las esperadas, comprueba primero si hay
NULLimplicados. La lógica de tres valores está detrás de la mayoría de los resultados "inexplicables".
Ejercicios
Ejercicio 1: Vocabulario formal sobre una relación
Dada esta instancia de la relación ejemplares de BiblioRed:
| ejemplar_id | codigo | libro_id | sucursal_id | estado | fecha_adquisicion |
|---|---|---|---|---|---|
| 1 | EJ-3081 | 331 | 2 | prestado | 2019-03-14 |
| 2 | EJ-3082 | 331 | 1 | disponible | 2019-03-14 |
| 3 | EJ-3083 | 331 | 3 | disponible | 2021-06-01 |
| 4 | EJ-3084 | 332 | 1 | prestado | 2015-11-20 |
Responde:
- ¿Cuál es el grado y cuál la cardinalidad?
- Propón un dominio razonable para
estadoy otro parafecha_adquisicion. - Indica dos superclaves, todas las claves candidatas, la clave primaria elegida y la clave alternativa.
- ¿Es
{libro_id, sucursal_id}clave candidata? Justifícalo con los datos. - Enumera las claves ajenas de esta relación y hacia dónde apuntan.
Ejercicio 2: Lógica de tres valores
La tabla prestamos contiene estas filas:
| prestamo_id | socio_id | fecha_devolucion | recargo |
|---|---|---|---|
| 1 | 14 | 2026-03-19 | 0.00 |
| 2 | 15 | 2026-04-02 | 1.40 |
| 9 | 14 | NULL | NULL |
| 12 | 19 | NULL | NULL |
Di cuántas filas devuelve cada consulta y por qué:
SELECT * FROM prestamos WHERE fecha_devolucion = NULL;SELECT * FROM prestamos WHERE fecha_devolucion IS NULL;SELECT * FROM prestamos WHERE recargo > 0;SELECT * FROM prestamos WHERE recargo > 0 OR fecha_devolucion IS NULL;SELECT * FROM prestamos WHERE socio_id = 14 AND recargo > 0;SELECT * FROM prestamos WHERE NOT (recargo > 0);
Ejercicio 3: Traducir preguntas a álgebra relacional
Expresa cada pregunta usando las operaciones del álgebra (σ, π, ⋈, ∪, −) y di qué cláusula SQL le corresponderá. No hace falta sintaxis SQL correcta todavía.
- Los códigos de los ejemplares que están en reparación.
- Los títulos de todos los libros, sin repetir.
- Cada ejemplar acompañado del título de su libro.
- Los socios que tienen préstamos o reservas.
- Los libros que nunca se han reservado.
Soluciones
Solución 1
- Grado 6 (seis atributos:
ejemplar_id,codigo,libro_id,sucursal_id,estado,fecha_adquisicion). Cardinalidad 4 (cuatro tuplas). El grado pertenece al esquema; la cardinalidad, a la instancia. - Para
estado, un dominio cerrado de etiquetas:{'disponible', 'prestado', 'reparacion', 'baja'}. Parafecha_adquisicion, las fechas válidas del calendario, no posteriores a hoy (una biblioteca no adquiere en el futuro). El primero se implementará con unCHECK, tema de 04-04. - Superclaves:
{ejemplar_id},{codigo},{ejemplar_id, estado},{codigo, libro_id, sucursal_id}, el conjunto de todos los atributos… Claves candidatas:{ejemplar_id}y{codigo}, porque ambas identifican y ninguna se puede reducir. Clave primaria:ejemplar_id(subrogada, estable, barata en las claves ajenas deprestamos). Clave alternativa:codigo, declaradaUNIQUE, porque la etiqueta física también debe ser única. - No. Con estos datos no se repite ninguna combinación, pero eso es casualidad de la instancia: nada impide que la sucursal 2 tenga dos ejemplares del libro 331 (de hecho es lo normal en una biblioteca). Las claves se determinan por las reglas del negocio, nunca inspeccionando una instancia concreta; una instancia solo puede refutar una clave candidata, jamás confirmarla.
libro_id→libros.libro_id, ysucursal_id→sucursales.sucursal_id. Ambas deberían serNOT NULL: un ejemplar sin libro no tiene sentido y un ejemplar sin sucursal no se puede localizar en la estantería.
Solución 2
| # | Filas | Motivo |
|---|---|---|
| 1 | 0 | fecha_devolucion = NULL da DESCONOCIDO en las cuatro filas (también donde el valor es NULL). El filtro solo deja pasar VERDADERO. Es la trampa clásica: no falla, calla. |
| 2 | 2 (préstamos 9 y 12) | IS NULL es el operador correcto; devuelve VERDADERO exactamente donde falta el valor. |
| 3 | 1 (préstamo 2) | Para el 1, 0.00 > 0 es FALSO. Para el 9 y el 12, NULL > 0 es DESCONOCIDO, y DESCONOCIDO no pasa el filtro. |
| 4 | 3 (préstamos 2, 9 y 12) | Fila 2: VERDADERO OR FALSO = VERDADERO. Filas 9 y 12: DESCONOCIDO OR VERDADERO = VERDADERO (basta con que una parte se cumpla). Fila 1: FALSO OR FALSO = FALSO. |
| 5 | 0 | Las filas del socio 14 son la 1 (0.00 > 0 es FALSO → V AND F = FALSO) y la 9 (NULL > 0 es DESCONOCIDO → V AND D = DESCONOCIDO, no pasa). |
| 6 | 1 (préstamo 1) | NOT FALSO = VERDADERO (fila 1). NOT VERDADERO = FALSO (fila 2). NOT DESCONOCIDO = DESCONOCIDO (filas 9 y 12): negar algo desconocido sigue siendo desconocido. Este es el punto más contraintuitivo: la 3 devuelve 1 fila y su negación también devuelve 1, no 3. |
Solución 3
| # | Álgebra relacional | Cláusula SQL |
|---|---|---|
| 1 | π codigo ( σ estado = 'reparacion' (ejemplares) ) |
SELECT codigo ... WHERE estado = 'reparacion' |
| 2 | π titulo (libros) — la proyección del álgebra ya elimina duplicados |
SELECT DISTINCT titulo FROM libros |
| 3 | ejemplares ⋈ ejemplares.libro_id = libros.libro_id libros |
JOIN ... ON (lección 02-04) |
| 4 | π socio_id (prestamos) ∪ π socio_id (reservas) |
UNION |
| 5 | π libro_id (libros) − π libro_id (reservas) |
EXCEPT (o un LEFT JOIN ... IS NULL, lección 02-04) |
Observa el patrón del punto 5: toda pregunta que empieza por "los que nunca…" es una diferencia. Retenlo, porque en 02-04 y en 02-06 volverá varias veces.
Conclusión
Hemos convertido el vocabulario informal de la primera lección en un modelo con reglas precisas:
- Una relación es un conjunto de tuplas con los mismos atributos, cada uno con su dominio. Su grado es el número de atributos y su cardinalidad, el de tuplas.
- Al ser un conjunto, no tiene orden ni duplicados, y eso la separa radicalmente de una hoja de cálculo, donde una fila se identifica por su posición y no por su valor.
- Las claves forman una jerarquía: superclave → clave candidata (superclave mínima) → clave primaria (la elegida) y claves alternativas (las demás,
UNIQUE). Las claves ajenas vinculan unas relaciones con otras. - En el debate clave natural frente a subrogada, BiblioRed elige
libro_idcomo primaria y conservaisbncomo alternativa: porque no todo tiene ISBN, porque el ISBN se corrige y porque un entero es más barato de replicar. - Las tres reglas de integridad: de dominio (los valores pertenecen a su tipo), de entidad (la clave primaria nunca es nula) y referencial (toda clave ajena apunta a algo que existe; su tratamiento práctico es la lección 02-06).
NULLsignifica "no sé", y de ahí la lógica de tres valores:NULL = NULLes DESCONOCIDO,IS NULLes el único operador válido para preguntar por su ausencia, yNOT DESCONOCIDOsigue siendo DESCONOCIDO.- El álgebra relacional —selección, proyección, producto cartesiano, reunión, unión, diferencia— es la maquinaria que SQL implementa: cada operación tiene su cláusula, y el optimizador de 01-04 no hace otra cosa que reordenarlas.
- Y tenemos el plano de BiblioRed:
sucursales,socios,autores,libros,ejemplares,prestamosyreservas, con sus claves y sus vínculos.
El plano está dibujado; falta levantarlo. En la lección 02-02, Lenguaje SQL, conocerás el lenguaje con el que se habla con un sistema relacional —por qué es declarativo, qué sublenguajes tiene, cómo se escriben sus tipos de datos— y terminarás ejecutando el script CREATE TABLE completo de las siete tablas dentro de biblioredb. Al acabarla, el diagrama de esta lección habrá dejado de ser un dibujo.
Fundamentos de Bases de Datos
Módulo 1: Introducción a las Bases de Datos
- Conceptos Básicos de Bases de Datos
- Tipos de Bases de Datos
- Historia y Evolución de las Bases de Datos
- Sistemas Gestores de Bases de Datos y Arquitectura
Módulo 2: Bases de Datos Relacionales
- Modelo Relacional
- Lenguaje SQL
- Operaciones Básicas en SQL
- Consultas Multitabla: JOIN y Subconsultas
- Agregación y Agrupación de Datos
- Integridad Referencial
Módulo 3: Bases de Datos No Relacionales
- Introducción a NoSQL
- Tipos de Bases de Datos NoSQL
- Modelado de Datos en NoSQL
- Comparación entre Bases de Datos Relacionales y No Relacionales
Módulo 4: Diseño de Esquemas
- Principios de Diseño de Esquemas
- Diagramas Entidad-Relación (ER)
- Transformación de Diagramas ER a Esquemas Relacionales
- Tipos de Datos y Restricciones
Módulo 5: Normalización
Módulo 6: Transacciones, Rendimiento y Seguridad
- Transacciones y Propiedades ACID
- Concurrencia y Niveles de Aislamiento
- Índices y Optimización de Consultas
- Seguridad, Permisos y Copias de Seguridad
Módulo 7: Ejercicios Prácticos
- Ejercicios de SQL
- Ejercicios de Diseño de Esquemas
- Ejercicios de Normalización
- Ejercicios de Consultas Avanzadas y Transacciones
Módulo 8: Casos de Estudio
- Caso de Estudio: Base de Datos Relacional
- Caso de Estudio: Base de Datos No Relacional
- Caso de Estudio: Persistencia Políglota
