Módulo 20: El modelo relacional
Objetivos del módulo
- Conocer el origen del modelo relacional (E. F. Codd, 1970) y los objetivos que perseguía
- Dominar los elementos de su estructura: dominio, atributo, tupla, relación, grado y cardinalidad
- Entender la definición matemática de relación como subconjunto de un producto cartesiano
- Distinguir entre esquema (intensión) y extensión (instancia) de una relación
- Manejar la terminología equivalente: relación/tabla/fichero, tupla/fila/registro, atributo/columna/campo
- Conocer las propiedades de las relaciones y en qué se diferencian de las tablas de SQL
- Identificar superclaves, claves candidatas, primarias, alternativas y ajenas
- Comprender los valores nulos y la lógica trivaluada (tablas de verdad con
NULL) - Clasificar las restricciones en inherentes y semánticas
- Aplicar la integridad de entidad y la integridad referencial con todas sus opciones de borrado y modificación
- Conocer las restricciones de dominio, de verificación (
CHECK), las aserciones y los disparadores - Explicar las 12 (13) reglas de Codd
- Escribir un esquema relacional con la notación del curso y dibujar su grafo relacional
- Expresar el esquema EMPRESA completo en notación relacional
1. Origen y objetivos del modelo relacional
1.1. Un artículo que cambió la informática
En junio de 1970, Edgar Frank Codd, matemático que trabajaba en el laboratorio de IBM en San José (California), publicó en la revista Communications of the ACM el artículo “A Relational Model of Data for Large Shared Data Banks” (“Un modelo relacional de datos para grandes bancos de datos compartidos”). En él proponía algo radicalmente distinto de lo que se usaba entonces (los modelos jerárquico y en red que viste en el módulo 02):
- Los datos se representan únicamente mediante relaciones (tablas), sin punteros ni cadenas físicas visibles para el usuario.
- Las relaciones se manipulan con operaciones sobre conjuntos, basadas en la teoría matemática de conjuntos y en la lógica de predicados de primer orden.
- El usuario dice qué datos quiere, no cómo llegar a ellos navegando registro a registro.
📘 Concepto: El modelo relacional es un modelo lógico de datos que representa la información como un conjunto de relaciones (tablas de valores), define restricciones de integridad sobre ellas y ofrece operadores (álgebra y cálculo relacional) para manipularlas. Tiene, por tanto, tres componentes: estructura, integridad y manipulación.
1.2. Cronología esencial
| Año | Hito |
|---|---|
| 1970 | Codd publica el modelo relacional en Communications of the ACM |
| 1972 | Codd define el álgebra y el cálculo relacional y el concepto de completitud relacional |
| 1974-1979 | Prototipos de investigación: System R (IBM, de donde nace SEQUEL, luego SQL) e Ingres (Universidad de Berkeley, lenguaje QUEL) |
| 1976 | Peter Chen publica el modelo Entidad/Relación, pensado como paso previo al diseño relacional |
| 1979 | Relational Software Inc. (la futura Oracle Corporation) comercializa Oracle V2, el primer SGBD relacional comercial con SQL |
| 1981 | Codd recibe el Premio Turing por su trabajo |
| 1983 | IBM lanza DB2 |
| 1985 | Codd publica en Computerworld sus 12 reglas para evaluar si un producto es realmente relacional |
| 1986-1987 | Primer estándar de SQL (ANSI X3.135-1986, ISO 9075:1987) |
| 1990 | Codd publica The Relational Model for Database Management: Version 2 (RM/V2), con 333 reglas |
1.3. Objetivos del modelo
Codd perseguía resolver los problemas de los sistemas de ficheros y de los modelos navegacionales (módulos 01 y 02). Sus objetivos fueron:
| Objetivo | Qué significa |
|---|---|
| Independencia física | Cambiar cómo se almacenan los datos (índices, ficheros, discos) no obliga a cambiar los programas |
| Independencia lógica | Añadir tablas o columnas, o reorganizar el esquema, afecta lo mínimo a las aplicaciones (gracias, entre otras cosas, a las vistas) |
| Flexibilidad | Cada usuario puede ver los datos como más le convenga (vistas) |
| Uniformidad | Una única estructura (la relación) para todo: datos, y también el propio catálogo del sistema |
| Sencillez | Las tablas son fáciles de entender para usuarios no informáticos |
| Base formal | Al apoyarse en matemáticas (conjuntos y lógica), el modelo se puede razonar, optimizar y verificar con rigor |
| Lenguajes declarativos | Consultas de alto nivel que operan sobre conjuntos completos, no registro a registro |
💡 Consejo: Cuando en una entrevista o examen te pregunten “¿por qué triunfó el modelo relacional?”, la respuesta corta es: independencia de datos + base matemática + sencillez. Las tres cosas juntas permitieron construir optimizadores de consultas automáticos, algo imposible en los modelos navegacionales.
1.4. El modelo relacional dentro del diseño
En el módulo 04 viste las tres fases del diseño. El modelo relacional es el modelo lógico por excelencia:
flowchart LR
REQ[Requisitos] --> CON["Diseño conceptual<br/>(modelo E/R)"]
CON --> LOG["Diseño lógico<br/>(modelo relacional)"]
LOG --> NOR["Normalización<br/>(módulos 19-20)"]
NOR --> FIS["Diseño físico<br/>(DDL en Oracle)"]
En este módulo estudias el modelo en sí; en el 13, cómo transformar un diagrama E/R en un esquema relacional; en el 14, cómo consultarlo con el álgebra relacional.
2. La estructura del modelo relacional
2.1. Dominio
📘 Concepto: Un dominio (domain) es un conjunto de valores atómicos del mismo tipo, con un nombre y un significado. Por ejemplo:
D_SALARIOS= números decimales positivos con dos decimales;D_PROVINCIAS= {Álava, Albacete, …, Zaragoza};D_ESTADOS_PEDIDO= {PENDIENTE, ENVIADO, ENTREGADO, CANCELADO}.
Un dominio se puede definir de dos formas:
- Por extensión: enumerando sus valores.
D_DESCATALOGADO = {'S', 'N'}. - Por intensión: indicando un tipo de datos y una condición.
D_DESCUENTO = números con dos decimales entre 0 y 100.
El dominio aporta significado: aunque emp_id y cliente_id sean ambos enteros de seis cifras, pertenecen a dominios semánticos distintos (identificadores de empleados frente a identificadores de clientes) y no tiene sentido compararlos. Codd insistía en que el SGBD debería impedir esas comparaciones; en la práctica, la mayoría de los SGBD solo comprueban el tipo de datos, que es una aproximación más pobre del dominio.
💡 Consejo: Oracle AI Database 26ai incorpora los dominios SQL (
CREATE DOMAIN), que acercan el SGBD a la idea original de Codd: un dominio con tipo, restricciones y valor por defecto reutilizable en muchas columnas. Lo verás en el bloque de DDL.
⚠️ Importante: Disponible desde Oracle 23ai. En versiones anteriores (19c, 21c) el dominio se simula con el tipo de datos más una restricción
CHECKen cada columna.
2.2. Atributo
📘 Concepto: Un atributo (attribute) es el papel que desempeña un dominio en una relación. Tiene un nombre único dentro de la relación y toma sus valores de un único dominio:
Dom(salario) = D_SALARIOS.
Varios atributos pueden compartir dominio. En EMPLEADOS, los atributos emp_id y jefe_id toman valores del mismo dominio (identificadores de empleado), pero con papeles distintos: “quién es el empleado” y “quién es su jefe”.
2.3. Relación: definición matemática
Dados los dominios D₁, D₂, …, Dₙ (no necesariamente distintos), su producto cartesiano D₁ × D₂ × … × Dₙ es el conjunto de todas las n-tuplas ordenadas ⟨v₁, v₂, …, vₙ⟩ tales que v₁ ∈ D₁, v₂ ∈ D₂, …, vₙ ∈ Dₙ.
📘 Concepto: Una relación r definida sobre los dominios D₁, …, Dₙ es un subconjunto del producto cartesiano de esos dominios: r ⊆ D₁ × D₂ × … × Dₙ. Cada elemento de la relación es una tupla.
💻 Ejemplo: Sean
D_NOMBRES = {Ana, Luis}yD_DEPTS = {10, 20, 30}. El producto cartesiano tiene 2 × 3 = 6 tuplas:
D_NOMBRES × D_DEPTS = { ⟨Ana,10⟩, ⟨Ana,20⟩, ⟨Ana,30⟩, ⟨Luis,10⟩, ⟨Luis,20⟩, ⟨Luis,30⟩ }
La relación TRABAJA_EN, que dice en qué departamento trabaja cada persona, es solo un subconjunto de esas combinaciones, las que son ciertas en el mundo real:
TRABAJA_EN = { ⟨Ana,10⟩, ⟨Luis,20⟩ } ⊆ D_NOMBRES × D_DEPTS
Por eso se dice que una relación representa un predicado: “la persona x trabaja en el departamento y”. Cada tupla es una proposición verdadera de ese predicado. Las combinaciones que no aparecen se consideran falsas (es la hipótesis del mundo cerrado, closed world assumption).
En la definición que se usa en bases de datos, los componentes de una tupla no se identifican por su posición sino por el nombre del atributo. Por eso es más exacto decir que una tupla es un conjunto de pares (atributo, valor):
t = { (emp_id, 120), (nombre, 'Pablo'), (salario, 3500), (dept_id, 30) }
Con esta definición el orden de los atributos deja de importar, como verás en las propiedades de las relaciones.
2.4. Tupla, grado y cardinalidad
| Término | Definición | En DEPARTAMENTOS de EMPRESA |
|---|---|---|
| Tupla (tuple) | Cada elemento de la relación: un valor para cada atributo | ⟨30, ‘INFORMÁTICA’, ‘Valencia’, 420000⟩ |
| Grado (degree) | Número de atributos de la relación. Forma parte del esquema y cambia muy rara vez | 4 (dept_id, nombre, localidad, presupuesto) |
| Cardinalidad (cardinality) | Número de tuplas de la relación en un momento dado. Cambia con cada inserción o borrado | 7 departamentos |
Una relación de grado 1 se llama unaria; de grado 2, binaria; de grado 3, ternaria; de grado n, n-aria.
⚠️ Importante: No confundas la cardinalidad de una relación (número de tuplas) con la cardinalidad de una relación E/R (las parejas (mín, máx) del módulo 06). Son conceptos distintos que comparten nombre.
2.5. Esquema e instancia
📘 Concepto: El esquema de relación (o intensión) es la parte estática: el nombre de la relación y la lista de sus atributos con sus dominios, R(A₁:D₁, A₂:D₂, …, Aₙ:Dₙ), más sus restricciones. La extensión (o instancia, u ocurrencia) es la parte dinámica: el conjunto de tuplas que contiene la relación en un instante concreto, r(R).
Analogía: el esquema es el molde de un formulario en papel (las casillas que tiene); la extensión es el montón de formularios rellenos que hay en el archivador hoy. Mañana habrá más formularios, pero el molde será el mismo.
Esquema de la relación (intensión):
DEPARTAMENTOS (dept_id: D_DEPT_ID, nombre: D_NOMBRES_DEP, localidad: D_LOCALIDADES, presupuesto: D_IMPORTES)
Una extensión (la que crea el script ../recursos/empresa_datos.sql):
| dept_id | nombre | localidad | presupuesto |
|---|---|---|---|
| 10 | DIRECCIÓN | Madrid | 500000 |
| 20 | VENTAS | Madrid | 350000 |
| 30 | INFORMÁTICA | Valencia | 420000 |
| 40 | CONTABILIDAD | Sevilla | 150000 |
| 50 | MARKETING | Barcelona | 200000 |
| 60 | LOGÍSTICA | Zaragoza | 180000 |
| 70 | INVESTIGACIÓN | Bilbao | NULL |
El conjunto de esquemas de relación de una base de datos, junto con sus restricciones de integridad, forma el esquema relacional (o esquema de la base de datos). El conjunto de las extensiones de todas sus relaciones en un instante es la instancia de la base de datos o estado de la base de datos.
⚠️ Importante: Las restricciones se definen sobre el esquema y deben cumplirse en todas las extensiones posibles, no solo en la actual. Que hoy no haya dos departamentos en la misma localidad (no es así: hay dos en Madrid) no te autorizaría a declarar
localidadcomo clave. Las claves y restricciones salen del significado de los datos, nunca de mirar los datos actuales.
2.6. Terminología equivalente
Según el contexto (teoría, SQL o sistemas de ficheros) se usan nombres distintos para lo mismo:
| Modelo relacional (formal) | SQL / SGBD (tablas) | Sistemas de ficheros |
|---|---|---|
| Relación (relation) | Tabla (table) | Fichero (file) |
| Tupla (tuple) | Fila (row) | Registro (record) |
| Atributo (attribute) | Columna (column) | Campo (field) |
| Dominio (domain) | Tipo de datos + restricciones (o DOMAIN) | Tipo de campo |
| Grado (degree) | Número de columnas | Número de campos |
| Cardinalidad (cardinality) | Número de filas | Número de registros |
| Esquema de relación | Definición de tabla (CREATE TABLE) | Descripción del registro |
| Extensión / instancia | Contenido de la tabla | Contenido del fichero |
| Clave primaria (primary key) | PRIMARY KEY | Campo clave |
💡 Consejo: En un examen de teoría usa siempre la terminología formal (relación, tupla, atributo). En un examen de SQL o en el trabajo, la de tablas (tabla, fila, columna). Mezclarlas no es un error grave, pero demuestra menos dominio.
3. Propiedades de las relaciones
Como una relación es un conjunto matemático, hereda sus propiedades. Son restricciones inherentes al modelo: no las declara el diseñador, vienen “de serie”.
| Propiedad | Explicación | Consecuencia |
|---|---|---|
| No hay tuplas duplicadas | Un conjunto no tiene elementos repetidos | Toda relación tiene al menos una clave (en el peor caso, todos sus atributos juntos) |
| Las tuplas no están ordenadas | Un conjunto no tiene orden | No existe “la primera fila” ni “la fila siguiente”; el orden se pide al consultar (ORDER BY) |
| Los atributos no están ordenados | Cada valor se identifica por el nombre del atributo, no por su posición | ⟨emp_id=120, nombre=Pablo⟩ y ⟨nombre=Pablo, emp_id=120⟩ son la misma tupla |
| Los valores son atómicos | Cada celda contiene un único valor indivisible del dominio (nada de listas ni grupos repetitivos) | Es la primera forma normal (1FN), que estudiarás en el módulo 20 |
| Cada atributo tiene un nombre distinto dentro de la relación | El nombre identifica el papel | No puede haber dos columnas nombre en la misma relación |
| Todos los valores de un atributo pertenecen a su dominio | Restricción de dominio | Un salario no puede ser ‘abc’ |
💻 Ejemplo: Esta “tabla” no es una relación válida, por tres motivos:
| emp_id | nombre | telefonos |
|---|---|---|
| 120 | Pablo | 600100120, 655000111 |
| 121 | Raquel | 600100121 |
| 120 | Pablo | 600100120, 655000111 |
- La tupla de Pablo está repetida (las relaciones no admiten duplicados).
telefonoscontiene una lista de valores: no es atómico.- (Un tercer problema, más sutil: si
emp_ides la clave, dos tuplas no pueden compartirla.)
La solución relacional es sacar los teléfonos a otra relación con una tupla por teléfono: TELEFONOS_EMP (emp_id, telefono). Es exactamente la regla de transformación de los atributos multivaluados que verás en el módulo 17.
3.1. ¿Qué significa “atómico”?
La atomicidad es relativa al uso que se va a hacer del dato. Una fecha 15/01/2010 es atómica si siempre la manejas completa, aunque internamente tenga día, mes y año. Una dirección C/ Mayor 5, 46001 Valencia puede tratarse como atómica si solo la imprimes en sobres, pero no si necesitas buscar clientes por código postal: en ese caso conviene descomponerla en calle, numero, cp y ciudad.
💡 Consejo: Pregúntate: “¿voy a necesitar consultar, filtrar o agrupar por una parte de este valor?”. Si la respuesta es sí, ese valor no es atómico para tu sistema y debes descomponerlo.
3.2. Relación frente a tabla
Una tabla de SQL es la representación práctica de una relación, pero no son exactamente lo mismo:
| Aspecto | Relación (teoría) | Tabla (SQL / Oracle) |
|---|---|---|
| Duplicados | Imposibles | Una tabla sin clave primaria ni UNIQUE admite filas repetidas; SELECT sin DISTINCT devuelve duplicados |
| Orden de filas | No existe | Físicamente hay un orden de almacenamiento, pero no está garantizado en los resultados sin ORDER BY |
| Orden de columnas | No existe | Las columnas tienen una posición (la de CREATE TABLE), que se usa en SELECT * o en INSERT ... VALUES sin lista de columnas |
| Valores nulos | No existían en la versión original (1970); Codd los añadió después | NULL está integrado en el lenguaje |
| Atomicidad | Obligatoria | Oracle permite tipos no atómicos (colecciones, JSON, objetos), que rompen la 1FN si se usan sin criterio |
| Nombre | Se habla de relación base y relación derivada | Tabla, vista, resultado de una consulta |
⚠️ Importante: En SQL, el resultado de
SELECT oficio FROM empleados;tiene 24 filas con oficios repetidos (es un multiconjunto o bag). En el álgebra relacional, la proyección deoficiosobreEMPLEADOSda 11 tuplas (sin repetidos). Para obtener lo mismo en SQL necesitasSELECT DISTINCT oficio FROM empleados;. Lo estudiarás a fondo en el módulo 18.
4. Claves
Las claves son el mecanismo que permite identificar cada tupla y relacionar unas relaciones con otras. Es uno de los temas más preguntados en cualquier examen de bases de datos, así que vamos a definirlas con precisión.
4.1. Superclave
📘 Concepto: Una superclave (superkey) de un esquema de relación R es un conjunto de atributos SK ⊆ R tal que, en cualquier extensión válida de R, no existen dos tuplas distintas t₁ y t₂ con t₁[SK] = t₂[SK]. Dicho de otro modo: los valores de SK identifican de forma única cada tupla.
Como las relaciones no tienen duplicados, el conjunto de todos los atributos es siempre una superclave. Y si SK es superclave, cualquier conjunto que lo contenga también lo es: {emp_id} es superclave de EMPLEADOS, y también {emp_id, nombre}, {emp_id, salario, dept_id}…
4.2. Clave candidata
📘 Concepto: Una clave candidata (candidate key) es una superclave irreducible (o mínima): si le quitas cualquier atributo, deja de ser superclave. Cumple dos propiedades:
- Unicidad: no hay dos tuplas con el mismo valor de la clave.
- Irreducibilidad (minimalidad): ningún subconjunto propio suyo cumple la unicidad.
💻 Ejemplo: En
EMPLEADOS, según el significado de los datos (y las restricciones de../recursos/empresa_crear.sql):
{emp_id}es clave candidata: cada empleado tiene un identificador distinto.{email}es clave candidata: el correo corporativo es único (restricciónuq_emp_email).{emp_id, email}es superclave, pero no es clave candidata: le sobra un atributo.{nombre, apellidos}no es superclave: puede haber dos personas que se llamen igual, aunque hoy no ocurra en los datos.
Una relación puede tener varias claves candidatas, y una clave candidata puede estar formada por varios atributos (clave compuesta). En LINEAS_PEDIDO, ni pedido_id ni num_linea identifican por sí solos una línea; la clave candidata es {pedido_id, num_linea}.
💡 Consejo: Si una relación tiene n atributos y una única clave candidata de k atributos, el número de superclaves es 2ⁿ⁻ᵏ (la clave más cualquier combinación de los n−k atributos restantes). En
DEPARTAMENTOScon la clave{dept_id}(n = 4, k = 1) habría 2³ = 8 superclaves… si no fuera porquenombretambién es clave candidata. Lo calcularás en los ejercicios.
4.3. Clave primaria y claves alternativas
📘 Concepto: La clave primaria (primary key, PK) es la clave candidata que el diseñador elige para identificar las tuplas de la relación. Las demás claves candidatas se llaman claves alternativas (alternate keys) o secundarias, y en SQL se declaran con
UNIQUE.
Criterios para elegir la clave primaria entre varias candidatas:
| Criterio | Por qué |
|---|---|
| Estable (no cambia con el tiempo) | Cambiar una PK obliga a cambiar todas las claves ajenas que la referencian |
| Siempre conocida (nunca nula) | Por la regla de integridad de entidad (sección 7) |
| Corta y simple | Se replica en cada clave ajena y en cada índice |
| Sin significado de negocio cambiante | El email de un empleado puede cambiar si se casa o cambia de dominio la empresa; su emp_id no |
Por eso en EMPRESA la PK de EMPLEADOS es emp_id y email queda como clave alternativa (UNIQUE); en CLIENTES la PK es cliente_id y el nif es clave alternativa.
4.4. Claves naturales y claves subrogadas
| Tipo | Definición | Ejemplos | Ventajas | Inconvenientes |
|---|---|---|---|---|
| Natural | Atributo con significado en el mundo real | NIF, ISBN, matrícula de un coche, código IATA de un aeropuerto | Tiene sentido para el usuario, evita duplicados reales | Puede cambiar, ser larga o no existir para todos (extranjeros sin NIF) |
| Subrogada (surrogate) o artificial | Valor sin significado generado por el sistema (secuencia, columna identidad) | emp_id, cliente_id, pedido_id | Estable, corta, nunca cambia | No evita duplicados reales por sí sola |
⚠️ Importante: Si usas una clave subrogada como PK, declara la clave natural como
UNIQUE(como hace EMPRESA con elnifde los clientes). Si no lo haces, nada impide dar de alta dos veces al mismo cliente con identificadores distintos.
4.5. Clave ajena (clave foránea)
📘 Concepto: Una clave ajena o clave foránea (foreign key, FK) de una relación R₂ es un conjunto de atributos FK de R₂ cuyos valores deben coincidir con los de la clave primaria (o una clave candidata) de otra relación R₁ (la relación referenciada), o bien ser nulos. R₂ es la relación que referencia (hija) y R₁ la relación referenciada (padre).
Condiciones formales:
- Los atributos de FK tienen los mismos dominios que los de la clave referenciada de R₁ (y el mismo número de atributos).
- Para cada tupla t₂ de R₂, o bien t₂[FK] es nulo, o bien existe una tupla t₁ en R₁ con t₁[PK] = t₂[FK].
💻 Ejemplo: En EMPRESA,
EMPLEADOS.dept_ides clave ajena que referenciaDEPARTAMENTOS.dept_id. El empleado 120 tienedept_id = 30y existe el departamento 30: correcto. El empleado 160 tienedept_idnulo (becario sin departamento): también correcto. Un empleado condept_id = 99violaría la restricción, porque no existe el departamento 99.
Particularidades importantes de las claves ajenas:
- Puede referenciar a la misma relación (clave ajena reflexiva o autorreferencia):
EMPLEADOS.jefe_id → EMPLEADOS(emp_id),CATEGORIAS.categoria_padre_id → CATEGORIAS(categoria_id). - No tiene por qué llamarse igual que la clave referenciada:
CLIENTES.comercial_idyPEDIDOS.empleado_idreferencianEMPLEADOS(emp_id). - Puede formar parte de la clave primaria:
LINEAS_PEDIDO.pedido_ides a la vez parte de la PK y clave ajena haciaPEDIDOS. EnASIGNACIONES, los dos atributos de la PK son claves ajenas. - Puede ser compuesta, si la clave referenciada es compuesta. En ese caso todos sus atributos se comparan juntos.
- Una relación puede tener varias claves ajenas, incluso varias hacia la misma relación (
PEDIDOStienecliente_id → CLIENTESyempleado_id → EMPLEADOS). - Puede admitir nulos o no, según la obligatoriedad de la participación en el modelo conceptual:
PEDIDOS.cliente_ides obligatoria (todo pedido es de un cliente),PEDIDOS.empleado_ides opcional (los pedidos online no los gestiona nadie).
4.6. Resumen de los tipos de clave
flowchart TB
SK["Superclaves<br/>(identifican de forma única)"] --> CK["Claves candidatas<br/>(superclaves irreducibles)"]
CK --> PK["Clave primaria<br/>(la elegida)"]
CK --> AK["Claves alternativas<br/>(las demás: UNIQUE)"]
PK -.referenciada por.-> FK["Claves ajenas<br/>(en otras relaciones)"]
5. Valores nulos y lógica trivaluada
5.1. ¿Qué es un nulo?
📘 Concepto: Un valor nulo (
NULL) es una marca que indica la ausencia de valor en un atributo. No es un valor del dominio: no es el cero, ni la cadena vacía, ni un espacio en blanco.
Un nulo puede significar cosas distintas, y el modelo relacional (y SQL) no las distingue:
| Significado | Ejemplo en EMPRESA |
|---|---|
| Desconocido: el valor existe pero no lo sabemos | El teléfono de Sara Ortiz (123) existe, pero no lo tenemos registrado |
| No aplicable: el atributo no tiene sentido para esa tupla | La comisión de un programador: no cobra comisiones porque no es vendedor |
| Inexistente / pendiente: todavía no hay valor | La fecha_envio del pedido 5022, que está pendiente de enviar |
| Sin información: no sabemos ni si existe | El email de Antonio Ruiz (cliente 1006): ¿no tiene o no nos lo dio? |
💻 Ejemplo: En EMPRESA, Sergio Jiménez (113) tiene
comision = 0y Carmen Ruiz (110) tienecomision = 500, mientras que Raquel Molina (121) tienecomision = NULL. No es lo mismo: Sergio es vendedor y este año no ha cobrado comisión (sabemos que es cero); Raquel es programadora y la comisión no se le aplica.
💡 Consejo: Codd propuso en RM/V2 dos marcas distintas, A-mark (aplicable pero desconocido) e I-mark (inaplicable). Ningún SGBD comercial las implementó. Si en tu sistema necesitas distinguir ambos casos, tendrás que hacerlo con otro atributo o con un diseño distinto (por ejemplo, una jerarquía en la que solo el subtipo VENDEDOR tenga comisión, módulo 17).
5.2. Lógica trivaluada
Al comparar algo con un nulo, el resultado no puede ser ni verdadero ni falso: ¿es NULL > 400? No lo sabemos. Por eso el modelo relacional usa una lógica de tres valores (three-valued logic, 3VL): verdadero (V), falso (F) y desconocido (D) (en SQL, UNKNOWN).
Reglas básicas:
- Cualquier comparación (
=,<>,<,>,<=,>=) en la que intervenga un nulo da D. InclusoNULL = NULLda D: dos valores desconocidos no tienen por qué ser iguales. - Cualquier operación aritmética con un nulo da nulo:
salario + NULLesNULL. - Para preguntar si algo es nulo se usan predicados especiales que siempre devuelven V o F:
IS NULLeIS NOT NULL.
Tablas de verdad del AND (conjunción):
| AND | V | F | D |
|---|---|---|---|
| V | V | F | D |
| F | F | F | F |
| D | D | F | D |
Tablas de verdad del OR (disyunción):
| OR | V | F | D |
|---|---|---|---|
| V | V | V | V |
| F | V | F | D |
| D | V | D | D |
Tabla de verdad del NOT (negación):
| p | NOT p |
|---|---|
| V | F |
| F | V |
| D | D |
💡 Consejo: Truco para recordarlas: interpreta V = 1, D = ½, F = 0. Entonces AND = mínimo, OR = máximo y NOT p = 1 − p. Por ejemplo, V AND D = mín(1, ½) = ½ = D; F OR D = máx(0, ½) = ½ = D; NOT D = 1 − ½ = ½ = D.
5.3. Cómo afecta a las consultas
⚠️ Importante: Una condición de búsqueda (en una selección del álgebra o en un
WHEREde SQL) solo devuelve las tuplas para las que la condición es V. Las que dan F y las que dan D se descartan.
💻 Ejemplo: Evalúa la condición
comision < 500sobre los 24 empleados de EMPRESA:
- Elena (300) y Sergio (0): V → se devuelven.
- Carmen (500) y David (800): F → se descartan.
- Los 20 empleados con comisión nula: D → también se descartan.
Resultado: 2 empleados. Y ahora la condición contraria,
NOT (comision < 500): Carmen y David dan V; Elena y Sergio, F; los 20 nulos dan NOT D = D, y se descartan. Resultado: 2 empleados. ¡2 + 2 = 4, no 24! Con nulos, una condición y su negación no cubren todas las tuplas.
Otras consecuencias que verás en SQL:
- Las funciones de agregado (
SUM,AVG,MAX…) ignoran los nulos;COUNT(*)cuenta filas yCOUNT(columna)cuenta valores no nulos. NOT INcon una subconsulta que devuelve algún nulo produce resultado vacío, porquex NOT IN (a, NULL)equivale ax <> a AND x <> NULL, que nunca puede ser V. Es una de las trampas más famosas de SQL (módulo 31).- En Oracle, la cadena vacía
''se trata comoNULL, a diferencia de lo que dice el estándar. - Las restricciones
CHECKfuncionan al revés que elWHERE: rechazan la fila solo si la condición es F. Si es D, la fila se acepta. Por esoCHECK (comision >= 0)no impide quecomisionsea nula.
6. Restricciones de integridad
📘 Concepto: Una restricción de integridad es una condición que deben cumplir todas las extensiones válidas de la base de datos para que representen fielmente la realidad. Una operación de actualización que viole una restricción debe ser rechazada o compensada por el SGBD.
Las restricciones se clasifican en dos grandes grupos:
6.1. Restricciones inherentes
Son las que impone el propio modelo, por su definición. El diseñador no las declara: cualquier base de datos relacional las cumple por el mero hecho de serlo.
- No hay dos tuplas iguales en una relación (consecuencia: existe siempre una clave primaria).
- El orden de las tuplas y de los atributos no es significativo.
- Cada atributo toma un único valor atómico de su dominio en cada tupla (1FN).
- Integridad de entidad: ningún atributo de la clave primaria puede ser nulo (sección 7). Algunos autores la consideran inherente y otros semántica; lo importante es que se cumple siempre en cuanto declaras la PK.
También son inherentes las limitaciones del modelo: por ejemplo, el modelo relacional no permite representar directamente una relación N:M entre dos relaciones ni un atributo multivaluado; hay que crear una relación nueva (módulo 17).
6.2. Restricciones semánticas (de usuario)
Son las que define el diseñador para reflejar las reglas del mundo real que se quiere modelar. El modelo ofrece mecanismos para declararlas y el SGBD se encarga de hacerlas cumplir.
| Restricción | Qué garantiza | En SQL / Oracle | Ejemplo en EMPRESA |
|---|---|---|---|
| Clave primaria | Unicidad y no nulidad de la clave elegida | PRIMARY KEY | pk_empleados |
| Unicidad (clave alternativa) | Unicidad de una clave candidata no elegida | UNIQUE | uq_emp_email, uq_cli_nif |
| Obligatoriedad (valor no nulo, VNN) | Que el atributo tenga siempre valor | NOT NULL | nn_emp_salario |
| Clave ajena (integridad referencial) | Que las referencias apunten a tuplas existentes | FOREIGN KEY ... REFERENCES | fk_emp_dept |
| De dominio | Que el valor pertenezca a un conjunto permitido | Tipo de datos, CHECK, DOMAIN | descatalogado IN ('S','N') |
| De verificación | Una condición sobre los valores de una misma fila | CHECK | ck_ped_fechas: fecha_envio >= fecha_pedido |
| Aserción | Una condición que afecta a varias filas o varias tablas | CREATE ASSERTION (estándar SQL; Oracle desde 26ai) | “Ningún departamento puede tener más de 10 empleados” |
| Disparador | Una acción que el SGBD ejecuta automáticamente ante un evento | CREATE TRIGGER (PL/SQL en Oracle) | Registrar en una tabla de auditoría cada cambio de salario |
En las secciones siguientes se estudian en detalle.
7. Integridad de entidad
📘 Concepto: Regla de integridad de entidad: ningún atributo que forme parte de la clave primaria de una relación puede tomar un valor nulo.
¿Por qué? Porque la clave primaria es el medio para identificar cada tupla, y por tanto cada objeto del mundo real. Si la PK fuese nula, tendríamos tuplas que no sabemos a qué objeto corresponden: un empleado “sin identificador” no se podría referenciar desde ningún pedido ni asignación, ni distinguir de otro.
⚠️ Importante: La regla afecta a cada uno de los atributos de una clave primaria compuesta. En
LINEAS_PEDIDO (pedido_id, num_linea, ...)no puede haber una línea conpedido_idnulo ni connum_lineanulo. Y solo se aplica a la clave primaria: las claves alternativas sí pueden admitir nulos (en Oracle, una columnaUNIQUEpuede tener varias filas conNULL), salvo que además las declaresNOT NULL.
En SQL, declarar PRIMARY KEY implica automáticamente UNIQUE + NOT NULL en todas sus columnas:
-- Extracto de ../recursos/empresa_crear.sql
CREATE TABLE lineas_pedido (
pedido_id NUMBER(8),
num_linea NUMBER(3),
-- ...
CONSTRAINT pk_lineas_pedido PRIMARY KEY (pedido_id, num_linea),
-- ...
);
Aunque las columnas pedido_id y num_linea no llevan NOT NULL explícito, la restricción pk_lineas_pedido lo impone.
8. Integridad referencial
8.1. La regla
📘 Concepto: Regla de integridad referencial: si una relación R₂ tiene una clave ajena FK que referencia la clave primaria PK de R₁, todo valor de FK en R₂ debe coincidir con un valor de PK existente en R₁ o bien ser completamente nulo.
Dicho de forma coloquial: no puede haber referencias “colgando” (dangling references): un empleado no puede pertenecer a un departamento que no existe; una línea de pedido no puede referirse a un producto inexistente.
8.2. ¿Qué operaciones pueden violarla?
| Operación | Sobre la relación hija (R₂, la que tiene la FK) | Sobre la relación padre (R₁, la referenciada) |
|---|---|---|
| Inserción | Puede violarla: insertar un empleado con dept_id = 99 | Nunca la viola: un departamento nuevo no tiene empleados |
| Borrado | Nunca la viola: borrar un empleado no deja nada colgando | Puede violarla: borrar el departamento 30, que tiene 6 empleados |
| Modificación | Puede violarla: cambiar el dept_id de un empleado a 99 | Puede violarla: cambiar el dept_id del departamento 30 a 35 |
Las inserciones y modificaciones en la hija que violan la regla simplemente se rechazan. Pero para el borrado y la modificación en la relación padre el modelo ofrece varias opciones (acciones referenciales), que el diseñador elige para cada clave ajena según la semántica del problema.
8.3. Opciones ante el borrado y la modificación
| Opción | Comportamiento al borrar/modificar una tupla padre referenciada | SQL estándar |
|---|---|---|
| Operación restringida | Se rechaza la operación mientras existan tuplas hijas que la referencien | NO ACTION (por defecto) o RESTRICT |
| Propagación en cascada | Se borran (o modifican) también, automáticamente, todas las tuplas hijas | CASCADE |
| Puesta a nulos | La FK de las tuplas hijas se pone a nulo (solo si la FK admite nulos) | SET NULL |
| Puesta a valor por defecto | La FK de las tuplas hijas toma su valor por defecto (que debe existir en la relación padre) | SET DEFAULT |
💡 Consejo: La diferencia entre
NO ACTIONyRESTRICTen el estándar es de momento de comprobación:RESTRICTcomprueba inmediatamente, antes de hacer nada;NO ACTIONcomprueba al final de la sentencia (o de la transacción, si la restricción es diferida). En la práctica, ambas acaban rechazando la operación.
Para ver el efecto de cada opción usaremos esta extensión reducida de EMPRESA:
DEPARTAMENTOS (padre)
| dept_id | nombre | localidad |
|---|---|---|
| 10 | DIRECCIÓN | Madrid |
| 30 | INFORMÁTICA | Valencia |
| 70 | INVESTIGACIÓN | Bilbao |
EMPLEADOS (hija; dept_id → DEPARTAMENTOS(dept_id); valor por defecto supuesto de dept_id: 10)
| emp_id | nombre | dept_id |
|---|---|---|
| 100 | Ana | 10 |
| 120 | Pablo | 30 |
| 121 | Raquel | 30 |
| 160 | Tomás | NULL |
Operación 1: borrar el departamento 70. Ningún empleado lo referencia, así que todas las opciones permiten el borrado sin más efectos.
Operación 2: borrar el departamento 30. Tiene dos empleados que lo referencian:
| Opción | Resultado en DEPARTAMENTOS | Resultado en EMPLEADOS |
|---|---|---|
Restringida (NO ACTION) | Error: no se borra nada | Sin cambios |
Cascada (CASCADE) | Se borra el 30 | Se borran 120 y 121 (quedan 100 y 160) |
Puesta a nulos (SET NULL) | Se borra el 30 | 120 y 121 quedan con dept_id = NULL |
Valor por defecto (SET DEFAULT) | Se borra el 30 | 120 y 121 pasan a dept_id = 10 |
Operación 3: modificar la clave del departamento 30 a 35.
| Opción | Resultado en DEPARTAMENTOS | Resultado en EMPLEADOS |
|---|---|---|
Restringida (NO ACTION) | Error: el 30 sigue siendo 30 | Sin cambios |
Cascada (CASCADE) | El 30 pasa a ser 35 | 120 y 121 pasan a dept_id = 35 |
Puesta a nulos (SET NULL) | El 30 pasa a ser 35 | 120 y 121 quedan con dept_id = NULL |
Valor por defecto (SET DEFAULT) | El 30 pasa a ser 35 | 120 y 121 pasan a dept_id = 10 |
⚠️ Importante: La cascada se propaga en cadena. En EMPRESA,
LINEAS_PEDIDO.pedido_idtieneON DELETE CASCADE. Si borras el pedido 5001, se borran automáticamente sus 3 líneas. SiPEDIDOS.cliente_idtambién tuvieraON DELETE CASCADE(no lo tiene), borrar el cliente 1001 borraría sus pedidos 5001, 5006 y 5021, y con ellos sus 7 líneas. Usa la cascada solo cuando la tupla hija no tiene sentido sin la padre (típicamente, entidades débiles).
8.4. Cómo elegir la opción
| Situación semántica | Opción recomendada | Ejemplo |
|---|---|---|
| La hija no tiene sentido sin la padre (dependencia en existencia, entidad débil) | Cascada | Líneas de un pedido; asignaciones de un proyecto que se elimina |
| La hija tiene valor histórico o legal y no debe perderse | Restringida | Pedidos de un cliente; líneas que referencian un producto |
| La hija puede seguir existiendo sin padre (participación opcional) | Puesta a nulos | Si se elimina un departamento, sus empleados quedan sin departamento hasta su reasignación |
| Existe un padre “comodín” razonable | Valor por defecto | Productos de una categoría eliminada pasan a la categoría “Sin clasificar” |
| La clave primaria nunca cambia (subrogada) | Modificación restringida | Las PK numéricas de EMPRESA |
8.5. Lo que soporta Oracle
| Acción | ¿Oracle la admite? | Sintaxis |
|---|---|---|
| Borrado restringido | Sí (comportamiento por defecto) | sin cláusula |
| Borrado en cascada | Sí | ON DELETE CASCADE |
| Borrado con puesta a nulos | Sí | ON DELETE SET NULL |
| Borrado con valor por defecto | No | — |
| Modificación restringida | Sí (comportamiento por defecto y única opción) | sin cláusula |
| Modificación en cascada, a nulos o a defecto | No (no existe ON UPDATE) | — |
⚠️ Importante: Oracle no implementa
ON UPDATEniSET DEFAULT. Si necesitas esos comportamientos, la solución es un disparador (trigger), que se programa en PL/SQL y se estudia en el Curso de Oracle PL/SQL. La mejor estrategia, en cualquier caso, es usar claves primarias que nunca cambien, y así la modificación en cascada no hace falta.
Las acciones referenciales de EMPRESA, tal como están en ../recursos/empresa_crear.sql:
-- Al borrar un pedido, se borran sus líneas
CONSTRAINT fk_lin_pedido FOREIGN KEY (pedido_id) REFERENCES pedidos (pedido_id) ON DELETE CASCADE,
-- Al borrar un proyecto, se borran sus asignaciones
CONSTRAINT fk_asi_proyecto FOREIGN KEY (proyecto_id) REFERENCES proyectos (proyecto_id) ON DELETE CASCADE
-- Todas las demás claves ajenas son restringidas (comportamiento por defecto)
8.6. Claves ajenas compuestas y nulos parciales
Si la clave ajena es compuesta, puede ocurrir que unos atributos sean nulos y otros no. El estándar SQL define tres modos de comparación (MATCH SIMPLE, MATCH PARTIAL y MATCH FULL). Oracle aplica el comportamiento simple: si alguno de los atributos de la FK es nulo, la restricción no se comprueba para esa fila. Para obligar a que la FK sea “toda nula o toda no nula” (como pide MATCH FULL) se añade un CHECK.
9. Otras restricciones semánticas
9.1. Restricciones de dominio
Limitan los valores que puede tomar un atributo. En la práctica se implementan con:
- El tipo de datos y su tamaño:
NUMBER(8,2),VARCHAR2(30),DATE. NOT NULLsi el atributo es obligatorio.CHECKcon una lista de valores o un rango:CHECK (estado IN ('PENDIENTE', 'ENVIADO', 'ENTREGADO', 'CANCELADO')),CHECK (descuento BETWEEN 0 AND 100).- Dominios SQL (
CREATE DOMAIN), desde Oracle 23ai.
9.2. Restricciones de verificación (CHECK)
📘 Concepto: Una restricción de verificación es una condición que debe cumplir cada tupla de una relación. Puede referirse a uno o a varios atributos de la misma tupla, pero no a otras tuplas ni a otras relaciones.
Ejemplos reales de EMPRESA:
| Restricción | Condición | Tipo |
|---|---|---|
ck_emp_salario | salario > 0 | Sobre un atributo |
ck_pro_descatalogado | descatalogado IN ('S', 'N') | Dominio por extensión |
ck_ped_fechas | fecha_envio >= fecha_pedido | Entre dos atributos de la misma tupla |
ck_pry_fechas | fecha_fin >= fecha_inicio | Entre dos atributos de la misma tupla |
ck_lin_descuento | descuento BETWEEN 0 AND 100 | Rango |
⚠️ Importante: Recuerda la lógica trivaluada: un
CHECKsolo rechaza la fila si la condición es F. El pedido 5022 tienefecha_envionula:NULL >= fecha_pedidoda D, y la fila se acepta. Es exactamente lo que se quiere (un pedido pendiente aún no tiene fecha de envío).
9.3. Aserciones
📘 Concepto: Una aserción (assertion) es una restricción independiente de cualquier tabla, que expresa una condición que debe cumplir la base de datos en su conjunto y que puede involucrar varias tuplas y varias relaciones.
Ejemplos de reglas que no se pueden expresar con CHECK porque afectan a varias filas o tablas:
- “La suma de los presupuestos de los proyectos de un departamento no puede superar el presupuesto del departamento.”
- “Un departamento no puede tener más de 10 empleados.”
- “El jefe de un empleado debe trabajar en el mismo departamento o en DIRECCIÓN.”
- “Todo pedido debe tener al menos una línea” (cardinalidad mínima 1 del lado de las líneas).
La aserción está definida en el estándar SQL desde SQL-92 con esta forma:
-- Sintaxis del estándar SQL (ilustrativa: Oracle NO admite esta aserción concreta)
CREATE ASSERTION as_max_empleados_dept CHECK (
NOT EXISTS (
SELECT dept_id
FROM empleados
GROUP BY dept_id
HAVING COUNT(*) > 10
)
);
Durante décadas ningún SGBD importante la implementó, por su coste de comprobación. Oracle AI Database 26ai la ha incorporado (a partir de la actualización 23.26.1), pero con restricciones importantes: la condición no puede usar funciones de agregado (COUNT, SUM…), ni subconsultas anidadas dentro de la subconsulta, ni la sintaxis JOIN ... ON (las combinaciones se escriben en el WHERE), y las combinaciones deben poder validarse de forma eficiente (en la práctica, siguiendo una clave ajena hacia una clave primaria). Por eso la aserción anterior, con GROUP BY y COUNT, falla en Oracle con ORA-08661: Aggregates are not supported.
Una regla que sí puede expresarse como aserción en Oracle 26ai es “un empleado no puede ser asignado a un proyecto antes de que este empiece”, porque relaciona dos tablas a través de la clave ajena proyecto_id:
CREATE ASSERTION as_asignacion_fecha CHECK (
NOT EXISTS (
SELECT 1
FROM asignaciones a, proyectos p
WHERE a.proyecto_id = p.proyecto_id
AND a.fecha_asignacion < p.fecha_inicio
)
);
Assertion created.
A partir de ese momento, cualquier sentencia que viole la regla es rechazada:
UPDATE asignaciones
SET fecha_asignacion = DATE '2024-01-01'
WHERE emp_id = 120 AND proyecto_id = 1;
ERROR at line 1:
ORA-08601: Assertion (CURSO.AS_ASIGNACION_FECHA) violated.
⚠️ Importante: Disponible desde Oracle AI Database 26ai (versión 23.26.1) y con las limitaciones descritas. En versiones anteriores (19c, 21c, 23ai), y en 26ai para reglas con agregados como “un departamento no puede tener más de 10 empleados”, estas reglas se implementan con disparadores, o se controlan desde la aplicación.
9.4. Disparadores
📘 Concepto: Un disparador (trigger) es un procedimiento almacenado que el SGBD ejecuta automáticamente cuando se produce un evento determinado (una inserción, un borrado o una modificación en una tabla). Sigue el esquema evento - condición - acción (ECA).
Los disparadores sirven para:
- Implementar restricciones que el modelo declarativo no permite (aserciones en versiones antiguas,
ON UPDATE CASCADE, cardinalidades máximas distintas de 1 y n). - Mantener atributos derivados (por ejemplo, el importe total de un pedido).
- Auditar cambios.
En Oracle los disparadores se escriben en PL/SQL, que queda fuera de este curso. Puedes estudiarlos en el Curso de Oracle PL/SQL.
💡 Consejo: Regla de oro profesional: usa restricciones declarativas (
PRIMARY KEY,UNIQUE,NOT NULL,FOREIGN KEY,CHECK,ASSERTION) siempre que puedas, y disparadores solo para lo que no se pueda declarar. Las restricciones declarativas son más rápidas, el optimizador las aprovecha y no tienen errores de programación.
10. Las reglas de Codd
10.1. Contexto
A principios de los años 80 muchos fabricantes anunciaban sus productos como “relacionales” solo porque mostraban los datos en tablas, aunque por dentro siguieran siendo navegacionales. En 1985 Codd publicó en la revista Computerworld dos artículos (“Is your DBMS really relational?” y “Does your DBMS run by the rules?”) con 12 reglas (numeradas del 1 al 12) más una regla 0 fundamental, para evaluar hasta qué punto un SGBD es realmente relacional. De ahí que se hable de “12 reglas” o de “13 reglas”.
10.2. Las reglas explicadas
Regla 0. Regla fundamental (de base). Todo sistema que se anuncie como relacional debe ser capaz de gestionar sus bases de datos exclusivamente mediante sus capacidades relacionales. Las demás reglas se derivan de esta.
Regla 1. Regla de la información. Toda la información de la base de datos se representa de una sola forma: como valores en tablas. Ni punteros ocultos, ni ficheros aparte, ni orden de registros con significado. Ejemplo: que Pablo trabaje en INFORMÁTICA se sabe porque su tupla contiene dept_id = 30, no porque su registro esté “encadenado” al del departamento.
Regla 2. Regla del acceso garantizado. Todo dato individual (cada valor atómico) debe ser accesible de forma lógica mediante la combinación de nombre de la tabla + valor de la clave primaria + nombre de la columna. Ejemplo: el salario de Pablo es “tabla EMPLEADOS, emp_id = 120, columna salario”. No hace falta saber en qué bloque del disco está.
Regla 3. Tratamiento sistemático de los valores nulos. El SGBD debe soportar los nulos para representar la información desconocida o inaplicable, de forma sistemática e independiente del tipo de datos (no vale usar -1 o 'N/A' como “nulo” en cada columna). Ejemplo: comision es nula para los no vendedores, sea cual sea su tipo.
Regla 4. Catálogo dinámico en línea basado en el modelo relacional. La descripción de la base de datos (el diccionario de datos o catálogo) se representa también como tablas, que los usuarios autorizados consultan con el mismo lenguaje que los datos. Ejemplo: en Oracle, SELECT table_name FROM user_tables; consulta el catálogo con SQL normal.
Regla 5. Regla del sublenguaje de datos completo. Debe existir al menos un lenguaje, con sintaxis textual bien definida, que permita de forma completa: definir datos, definir vistas, manipular datos, definir restricciones de integridad, gestionar autorizaciones y controlar transacciones. Ejemplo: SQL con sus sublenguajes DDL, DML y DCL y las sentencias de transacción.
Regla 6. Regla de actualización de vistas. Todas las vistas que teóricamente sean actualizables deben poder actualizarse desde el sistema. Ejemplo: una vista con los empleados del departamento 30 es actualizable (cada fila corresponde a una fila de EMPLEADOS); una vista con el salario medio por departamento no lo es. Ningún SGBD cumple esta regla al 100 %, porque decidir si una vista es actualizable es un problema difícil.
Regla 7. Inserción, actualización y borrado de alto nivel. Las operaciones de manipulación deben trabajar sobre conjuntos de filas a la vez, no solo fila a fila. Ejemplo: UPDATE empleados SET salario = salario * 1.03 WHERE dept_id = 30; sube el sueldo a 6 empleados con una sola sentencia.
Regla 8. Independencia física de los datos. Los programas y las consultas no deben verse afectados por cambios en el almacenamiento físico ni en los métodos de acceso. Ejemplo: crear un índice sobre empleados(apellidos) o mover la tabla a otro tablespace no obliga a cambiar ninguna consulta.
Regla 9. Independencia lógica de los datos. Los programas no deben verse afectados por cambios en las tablas base que preserven la información (añadir columnas, dividir una tabla en dos…). Ejemplo: si EMPLEADOS se divide en dos tablas, una vista con el nombre y la estructura antiguos permite que las aplicaciones sigan funcionando.
Regla 10. Independencia de la integridad. Las restricciones de integridad deben definirse en el sublenguaje de datos y almacenarse en el catálogo, no en los programas de aplicación. Ejemplo: la regla “el salario debe ser positivo” es la restricción ck_emp_salario de la tabla, no un if repetido en cada programa Java o PHP.
Regla 11. Independencia de la distribución. Los usuarios no deben notar si la base de datos está distribuida en varias máquinas o centralizada en una: las consultas son las mismas. Ejemplo: las tablas de un sistema distribuido en Madrid y Valencia se consultan igual que si estuvieran en un solo servidor.
Regla 12. Regla de la no subversión. Si el sistema ofrece un lenguaje de bajo nivel (registro a registro), ese lenguaje no puede usarse para saltarse las reglas de integridad definidas en el lenguaje de alto nivel. Ejemplo: una herramienta de carga masiva no debe permitir insertar empleados con un dept_id inexistente si existe la restricción fk_emp_dept (o, si la desactiva temporalmente, debe volver a validarla).
10.3. Clasificación de las reglas
| Grupo | Reglas |
|---|---|
| Fundamental | 0 |
| Estructura y representación de la información | 1, 2, 3, 4 |
| Lenguaje y manipulación | 5, 6, 7 |
| Independencia de datos | 8, 9, 10, 11 |
| Seguridad e integridad | 10, 12 |
💡 Consejo: Ningún SGBD comercial cumple las 12 reglas al 100 % (la 6 y la 11 son las más difíciles). Lo importante no es “aprobar” sino entender qué ventaja aporta cada regla: casi todas giran en torno a la independencia entre los datos, su almacenamiento y los programas.
11. Notación del esquema relacional y grafo relacional
11.1. Notación textual del curso
En todo el curso los esquemas relacionales se escriben así, una línea por relación:
DEPARTAMENTOS (dept_id, nombre, localidad (N), presupuesto (N))
EMPLEADOS (emp_id, nombre, apellidos, email, telefono (N), fecha_alta, oficio, salario, comision (N), jefe_id (N), dept_id (N))
- jefe_id → EMPLEADOS(emp_id)
- dept_id → DEPARTAMENTOS(dept_id)
Convenciones:
| Elemento | Notación | Ejemplo |
|---|---|---|
| Nombre de la relación | MAYÚSCULAS, en plural (como las tablas) | EMPLEADOS |
| Clave primaria | Subrayada | emp_id; compuesta: (pedido_id, num_linea) |
| Clave ajena | En cursiva, con su referencia detallada debajo | dept_id, y debajo dept_id → DEPARTAMENTOS(dept_id) |
| Atributo que admite nulos | Sufijo (N). Los atributos sin marca son obligatorios (no nulos) | comision (N) |
| Clave alternativa | Línea UK: debajo de la relación | UK: email |
| Restricción de verificación | Línea CHECK: debajo de la relación | CHECK: salario > 0 |
| Acción referencial distinta de la restringida | Entre corchetes tras la FK | pedido_id → PEDIDOS(pedido_id) [ON DELETE CASCADE] |
⚠️ Importante: Los atributos de la clave primaria nunca llevan
(N), por la regla de integridad de entidad. Un atributo que es a la vez parte de la PK y clave ajena se escribe subrayado y en cursiva: (*pedido_id*, num_linea, …).
Otras notaciones que encontrarás en libros y apuntes:
| Notación alternativa | Ejemplo |
|---|---|
PK con # o PK, FK con FK | EMPLEADOS (#emp_id, nombre, dept_id(FK)) |
| Clave ajena con flecha sobre el atributo | dept_id ↑ DEPARTAMENTOS |
| Formato tabular con una fila de cabecera | Muy habitual en herramientas CASE |
| Diagrama de tablas en pata de gallo | erDiagram de Mermaid (lo ves al final de este módulo) |
11.2. El grafo relacional
📘 Concepto: El grafo relacional (o diagrama referencial) representa cada relación como un nodo y cada clave ajena como una flecha que va desde la relación que referencia (hija) hasta la referenciada (padre). Permite ver de un vistazo las dependencias entre tablas.
Para qué sirve el grafo:
- Decidir el orden de creación de las tablas (primero las padres) y el orden de carga de datos.
- Decidir el orden de borrado (primero las hijas): el script
../recursos/empresa_borrar.sqlborra en orden inverso. - Ver las cadenas de cascada.
- Detectar ciclos de referencias, que exigen restricciones diferidas o crear la FK después con
ALTER TABLE.
flowchart RL
EMPLEADOS -->|dept_id| DEPARTAMENTOS
EMPLEADOS -->|jefe_id| EMPLEADOS
12. El esquema EMPRESA en notación relacional
Este es el esquema relacional completo de EMPRESA, obtenido de ../recursos/empresa_crear.sql. Es la “fuente de verdad” de todos los ejemplos SQL del curso. En el módulo 17 verás de qué diagrama E/R procede.
12.1. Esquema relacional completo
DEPARTAMENTOS (dept_id, nombre, localidad (N), presupuesto (N))
- UK: nombre
- CHECK: presupuesto >= 0
EMPLEADOS (emp_id, nombre, apellidos, email, telefono (N), fecha_alta, oficio, salario, comision (N), jefe_id (N), dept_id (N))
- jefe_id → EMPLEADOS(emp_id)
- dept_id → DEPARTAMENTOS(dept_id)
- UK: email
- CHECK: salario > 0; comision >= 0
CLIENTES (cliente_id, nombre, nif, email (N), telefono (N), ciudad (N), provincia (N), fecha_alta, limite_credito (N), comercial_id (N))
- comercial_id → EMPLEADOS(emp_id)
- UK: nif
- CHECK: limite_credito >= 0
- Valores por defecto: fecha_alta = fecha actual; limite_credito = 3000
CATEGORIAS (categoria_id, nombre, categoria_padre_id (N))
- categoria_padre_id → CATEGORIAS(categoria_id)
- UK: nombre
PRODUCTOS (producto_id, nombre, descripcion (N), categoria_id, precio, stock, fecha_alta (N), descatalogado)
- categoria_id → CATEGORIAS(categoria_id)
- CHECK: precio >= 0; stock >= 0; descatalogado IN (‘S’, ‘N’)
- Valores por defecto: stock = 0; descatalogado = ‘N’
PEDIDOS (pedido_id, cliente_id, empleado_id (N), fecha_pedido, fecha_envio (N), estado)
- cliente_id → CLIENTES(cliente_id)
- empleado_id → EMPLEADOS(emp_id)
- CHECK: estado IN (‘PENDIENTE’, ‘ENVIADO’, ‘ENTREGADO’, ‘CANCELADO’); fecha_envio >= fecha_pedido
- Valores por defecto: fecha_pedido = fecha actual; estado = ‘PENDIENTE’
LINEAS_PEDIDO (*pedido_id*, num_linea, producto_id, cantidad, precio_unitario, descuento)
- pedido_id → PEDIDOS(pedido_id) [ON DELETE CASCADE]
- producto_id → PRODUCTOS(producto_id)
- CHECK: cantidad > 0; precio_unitario >= 0; descuento BETWEEN 0 AND 100
- Valores por defecto: descuento = 0
PROYECTOS (proyecto_id, nombre, dept_id (N), fecha_inicio, fecha_fin (N), presupuesto (N))
- dept_id → DEPARTAMENTOS(dept_id)
- UK: nombre
- CHECK: fecha_fin >= fecha_inicio; presupuesto >= 0
ASIGNACIONES (*emp_id*, *proyecto_id*, fecha_asignacion, horas (N), funcion (N))
- emp_id → EMPLEADOS(emp_id)
- proyecto_id → PROYECTOS(proyecto_id) [ON DELETE CASCADE]
- CHECK: horas >= 0
- Valores por defecto: fecha_asignacion = fecha actual; horas = 0
12.2. Análisis del esquema
| Relación | Grado | Cardinalidad (datos del curso) | Clave primaria | Claves alternativas | Claves ajenas |
|---|---|---|---|---|---|
| DEPARTAMENTOS | 4 | 7 | dept_id | nombre | — |
| EMPLEADOS | 11 | 24 | emp_id | jefe_id, dept_id | |
| CLIENTES | 10 | 14 | cliente_id | nif | comercial_id |
| CATEGORIAS | 3 | 11 | categoria_id | nombre | categoria_padre_id |
| PRODUCTOS | 8 | 20 | producto_id | — | categoria_id |
| PEDIDOS | 6 | 24 | pedido_id | — | cliente_id, empleado_id |
| LINEAS_PEDIDO | 6 | 51 | (pedido_id, num_linea) | — | pedido_id, producto_id |
| PROYECTOS | 6 | 5 | proyecto_id | nombre | dept_id |
| ASIGNACIONES | 5 | 14 | (emp_id, proyecto_id) | — | emp_id, proyecto_id |
Observaciones de diseño:
- Hay dos autorreferencias (claves ajenas reflexivas):
EMPLEADOS.jefe_id(jerarquía de mando) yCATEGORIAS.categoria_padre_id(árbol de categorías). Ambas admiten nulos: la directora general (100) no tiene jefe y las categorías raíz (1, 7, 10) no tienen padre. EMPLEADOSes la relación más referenciada: la referencianEMPLEADOS,CLIENTES,PEDIDOSyASIGNACIONES, con cuatro papeles distintos (jefe, comercial, gestor del pedido, miembro de proyecto).LINEAS_PEDIDOyASIGNACIONEStienen clave primaria compuesta en la que participan claves ajenas.- Solo dos claves ajenas tienen borrado en cascada: las de las relaciones que no tienen sentido sin su padre.
- Todas las claves primarias son subrogadas (números sin significado), y las claves naturales (
nif,email, nombres) se protegen conUNIQUE.
12.3. Grafo relacional de EMPRESA
flowchart RL
EMPLEADOS -->|dept_id| DEPARTAMENTOS
EMPLEADOS -->|jefe_id| EMPLEADOS
CLIENTES -->|comercial_id| EMPLEADOS
CATEGORIAS -->|categoria_padre_id| CATEGORIAS
PRODUCTOS -->|categoria_id| CATEGORIAS
PEDIDOS -->|cliente_id| CLIENTES
PEDIDOS -->|empleado_id| EMPLEADOS
LINEAS_PEDIDO -->|"pedido_id (cascada)"| PEDIDOS
LINEAS_PEDIDO -->|producto_id| PRODUCTOS
PROYECTOS -->|dept_id| DEPARTAMENTOS
ASIGNACIONES -->|emp_id| EMPLEADOS
ASIGNACIONES -->|"proyecto_id (cascada)"| PROYECTOS
Del grafo se deduce un orden de creación válido (ninguna tabla antes que las que referencia): DEPARTAMENTOS → EMPLEADOS → CLIENTES → CATEGORIAS → PRODUCTOS → PEDIDOS → LINEAS_PEDIDO → PROYECTOS → ASIGNACIONES, que es justo el orden de ../recursos/empresa_crear.sql. Las autorreferencias no dan problemas de creación, pero sí de carga de datos: hay que insertar primero a los jefes (por eso el script de datos inserta a Ana, 100, antes que a nadie) y las categorías padre antes que las hijas.
12.4. El mismo esquema en diagrama de tablas
La notación de pata de gallo de erDiagram es otra forma habitual de dibujar un esquema relacional (las herramientas como SQL Developer Data Modeler la usan):
erDiagram
DEPARTAMENTOS ||--o{ EMPLEADOS : "dept_id"
EMPLEADOS |o--o{ EMPLEADOS : "jefe_id"
EMPLEADOS |o--o{ CLIENTES : "comercial_id"
CATEGORIAS |o--o{ CATEGORIAS : "categoria_padre_id"
CATEGORIAS ||--o{ PRODUCTOS : "categoria_id"
CLIENTES ||--o{ PEDIDOS : "cliente_id"
EMPLEADOS |o--o{ PEDIDOS : "empleado_id"
PEDIDOS ||--|{ LINEAS_PEDIDO : "pedido_id"
PRODUCTOS ||--o{ LINEAS_PEDIDO : "producto_id"
DEPARTAMENTOS |o--o{ PROYECTOS : "dept_id"
EMPLEADOS ||--o{ ASIGNACIONES : "emp_id"
PROYECTOS ||--o{ ASIGNACIONES : "proyecto_id"
⚠️ Importante: Fíjate en
PEDIDOS ||--|{ LINEAS_PEDIDO: el modelo conceptual dice que todo pedido tiene al menos una línea, pero el esquema relacional no puede garantizarlo con claves ajenas (nada impide crear un pedido sin líneas). Es una restricción que se “pierde” en la transformación; en el módulo 17 verás cómo recuperarla.
13. Ejercicios
Ejercicio 1: Grado, cardinalidad y dominios
Dada la extensión de PROYECTOS de EMPRESA:
| proyecto_id | nombre | dept_id | fecha_inicio | fecha_fin | presupuesto |
|---|---|---|---|---|---|
| 1 | Migración a la nube | 30 | 07/01/2025 | 30/09/2025 | 120000 |
| 2 | Nueva tienda online | 30 | 01/06/2025 | NULL | 90000 |
| 3 | Campaña Navidad 2025 | 50 | 01/10/2025 | 31/12/2025 | 40000 |
| 4 | Optimización de almacén | 60 | 01/02/2026 | NULL | 35000 |
| 5 | Plan estratégico 2027 | 10 | 01/09/2026 | NULL | NULL |
a) Indica su grado y su cardinalidad. b) Propón un dominio (por intensión) para cada atributo. c) ¿Qué ocurre con el grado y la cardinalidad si se inserta un sexto proyecto? ¿Y si se añade la columna responsable_id?
Ver solución
a) Grado 6 (seis atributos) y cardinalidad 5 (cinco tuplas).
b) Una propuesta:
| Atributo | Dominio |
|---|---|
| proyecto_id | Enteros positivos de hasta 4 cifras |
| nombre | Cadenas de hasta 60 caracteres, no vacías |
| dept_id | Enteros de hasta 4 cifras (el mismo dominio que DEPARTAMENTOS.dept_id) |
| fecha_inicio, fecha_fin | Fechas del calendario |
| presupuesto | Decimales con 2 decimales, mayores o iguales que 0, de hasta 12 dígitos |
c) Insertar un proyecto cambia la cardinalidad (pasa a 6), porque cambia la extensión. Añadir una columna cambia el grado (pasa a 7), porque cambia el esquema. El primer cambio es una operación habitual de DML; el segundo, una modificación del esquema con DDL (ALTER TABLE).
Ejercicio 2: ¿Es una relación?
Indica qué propiedades de las relaciones incumple esta tabla y cómo la corregirías:
| nif | nombre | ciudad | pedidos |
|---|---|---|---|
| B12345678 | Talleres Martín S.L. | Valencia | 5001, 5006, 5021 |
| A23456789 | Construcciones Levante S.A. | Alicante | 5002, 5009, 5018 |
| B12345678 | Talleres Martín S.L. | Valencia | 5001, 5006, 5021 |
Ver solución
- Tupla duplicada: la primera y la tercera son idénticas. Una relación es un conjunto y no admite duplicados.
- Valores no atómicos: el atributo
pedidoscontiene una lista de valores (un grupo repetitivo). Incumple la 1FN.
Corrección: eliminar la tupla repetida y llevar los pedidos a otra relación en la que cada pedido sea una tupla que referencie al cliente. Es exactamente lo que hace EMPRESA:
CLIENTES (cliente_id, nombre, nif, ciudad (N), …)
PEDIDOS (pedido_id, cliente_id, …)
- cliente_id → CLIENTES(cliente_id)
Ahora la información “el cliente 1001 tiene los pedidos 5001, 5006 y 5021” se representa con tres tuplas de PEDIDOS, y se puede consultar, contar y filtrar con facilidad.
Ejercicio 3: Superclaves y claves candidatas
Para la relación DEPARTAMENTOS (dept_id, nombre, localidad, presupuesto), sabiendo que dept_id y nombre son únicos (y nada más lo es):
a) Enumera sus claves candidatas. b) Calcula cuántas superclaves tiene y enuméralas. c) ¿Es {localidad} clave candidata? Razónalo con los datos y sin ellos.
Ver solución
a) Claves candidatas: {dept_id} y {nombre}. Ambas son únicas y, al tener un solo atributo, son irreducibles.
b) Una superclave es cualquier conjunto que contenga dept_id o nombre.
- Conjuntos que contienen
dept_id: 2³ = 8 (dept_id combinado con cualquier subconjunto de los otros tres). - Conjuntos que contienen
nombre: 8. - Conjuntos que contienen ambos (contados dos veces): 2² = 4.
- Total: 8 + 8 − 4 = 12 superclaves.
Son: {dept_id}, {nombre}, {dept_id, nombre}, {dept_id, localidad}, {dept_id, presupuesto}, {nombre, localidad}, {nombre, presupuesto}, {dept_id, nombre, localidad}, {dept_id, nombre, presupuesto}, {dept_id, localidad, presupuesto}, {nombre, localidad, presupuesto} y {dept_id, nombre, localidad, presupuesto}.
c) No. Con los datos actuales ya se ve que no es única (DIRECCIÓN y VENTAS están en Madrid). Pero aunque todos los departamentos estuvieran en ciudades distintas, tampoco lo sería: nada en el significado del problema impide abrir dos departamentos en la misma ciudad. Las claves se deducen de la semántica, no de la extensión.
Ejercicio 4: Lógica trivaluada sobre EMPRESA
Para cada condición, indica cuántos de los 24 empleados la cumplen. Datos relevantes: solo 4 empleados tienen comisión no nula (Carmen 500, David 800, Elena 300 y Sergio 0); todos los demás tienen comision nula. El único empleado sin departamento es Tomás (160), y la única con jefe_id nulo es Ana (100).
a) comision >= 0 b) comision IS NULL c) comision > 400 OR salario > 3000 d) NOT (dept_id = 30) e) dept_id = 30 OR dept_id <> 30 f) jefe_id = jefe_id
Ver solución
a) 4. Las 4 comisiones no nulas son ≥ 0 (V); las 20 nulas dan D y se descartan.
b) 20. IS NULL nunca da D: es V para las 20 comisiones nulas.
c) 9. Por la parte del OR de la comisión: Carmen y David (V). Por la del salario > 3000: Ana, Luis, Marta, Pedro, Laura, Javier y Pablo (7), que tienen comisión nula: D OR V = V. Total 2 + 7 = 9. El resto da F OR F = F o D OR F = D.
d) 17. De los 24 empleados, 6 están en el 30 (F). Tomás tiene dept_id nulo: NOT D = D, se descarta. Quedan 24 − 6 − 1 = 17.
e) 23. Parece una tautología, pero para Tomás da D OR D = D. Con nulos, ni siquiera “p OR NOT p” es siempre verdadero.
f) 23. Para Ana, NULL = NULL da D. Se descarta.
Ejercicio 5: Integridad referencial en EMPRESA
Usando el esquema real de EMPRESA (sección 12) y sus datos, indica qué ocurre con cada operación y por qué:
a) Borrar el departamento 70. b) Borrar el departamento 40. c) Borrar el producto 14. d) Borrar el producto 6. e) Borrar el pedido 5002. f) Borrar el proyecto 1. g) Borrar el empleado 113. h) Insertar un empleado con dept_id = 80. i) Cambiar el cliente_id del cliente 1013 a 2013.
Ver solución
a) Se borra. Ningún empleado ni proyecto lo referencia.
b) Error. Los empleados 103, 130 y 131 lo referencian a través de fk_emp_dept, que es restringida.
c) Se borra. El producto 14 (descatalogado) no aparece en ninguna línea de pedido.
d) Error. El ratón (6) aparece en líneas de los pedidos 5001, 5006 y 5014; fk_lin_producto es restringida.
e) Se borra el pedido y, en cascada, sus 3 líneas, por el ON DELETE CASCADE de fk_lin_pedido.
f) Se borra el proyecto y, en cascada, sus 3 asignaciones (empleados 120, 121 y 124), por el ON DELETE CASCADE de fk_asi_proyecto.
g) Error. Sergio (113) es el comercial de los clientes 1008, 1011 y 1014 (fk_cli_comercial) y gestiona los pedidos 5008, 5017 y 5024 (fk_ped_empleado). Basta con una de las dos referencias para que el borrado restringido falle.
h) Error. No existe el departamento 80: viola fk_emp_dept.
i) Se modifica. El cliente 1013 no tiene pedidos, así que no hay referencias que romper. Si hubiera tenido pedidos, Oracle lo rechazaría (no hay ON UPDATE CASCADE).
Ejercicio 6: Elegir acciones referenciales
En una base de datos de una biblioteca existen las relaciones SOCIOS, LIBROS, EJEMPLARES (cada ejemplar es una copia física de un libro), PRESTAMOS (qué socio se lleva qué ejemplar y cuándo) y GENEROS (cada libro tiene opcionalmente un género). Elige la acción ante el borrado más adecuada para cada clave ajena y justifícala:
a) EJEMPLARES.isbn → LIBROS(isbn) b) PRESTAMOS.socio_id → SOCIOS(socio_id) c) PRESTAMOS.ejemplar_id → EJEMPLARES(ejemplar_id) d) LIBROS.genero_id → GENEROS(genero_id)
Ver solución
a) Cascada. Un ejemplar no tiene sentido sin su libro: si se elimina un libro del catálogo, se eliminan sus copias (aunque, como veremos en c, si alguna copia tiene préstamos, la cascada se detendrá con un error).
b) Restringida. Los préstamos son un histórico con valor (estadísticas, sanciones). No se debe poder borrar un socio con préstamos; si se da de baja, mejor marcarlo como inactivo.
c) Restringida, por la misma razón: el historial de préstamos de un ejemplar no debe desaparecer.
d) Puesta a nulos. El género es opcional: si se elimina un género, los libros siguen existiendo sin clasificar. Como alternativa, valor por defecto si existe un género “Sin clasificar” (en Oracle habría que programarla con un disparador).
Ejercicio 7: Identificar reglas de Codd
Indica qué regla de Codd se cumple o se incumple en cada situación:
a) Un SGBD guarda la lista de tablas en un fichero binario que solo se puede leer con una utilidad propia. b) Al crear un índice sobre pedidos(fecha_pedido), las consultas existentes siguen funcionando sin cambios y más rápido. c) Para poner a nulo un dato desconocido hay que escribir -1 en las columnas numéricas y '?' en las de texto. d) Una utilidad de importación permite cargar líneas de pedido con productos inexistentes aunque exista fk_lin_producto. e) DELETE FROM lineas_pedido WHERE pedido_id = 5002; borra las tres líneas de una vez.
Ver solución
a) Incumple la regla 4 (catálogo dinámico en línea basado en el modelo relacional): el catálogo debería ser un conjunto de tablas consultables con el lenguaje normal.
b) Cumple la regla 8 (independencia física).
c) Incumple la regla 3 (tratamiento sistemático de nulos): el nulo debe ser una marca única e independiente del tipo de datos.
d) Incumple la regla 12 (no subversión).
e) Cumple la regla 7 (operaciones de alto nivel sobre conjuntos de filas).
Ejercicio 8: Esquema relacional de un videoclub online
Una plataforma de streaming almacena: usuarios (id, email único, nombre, fecha de alta y, opcionalmente, teléfono), planes de suscripción (código, nombre único, precio mensual mayor que 0), y títulos (id, título, año, duración en minutos opcional). Cada usuario está suscrito a un único plan obligatoriamente. Los usuarios valoran títulos con una puntuación de 1 a 5 y una fecha; un usuario solo puede valorar una vez cada título. Si se borra un usuario, deben desaparecer sus valoraciones; un plan con usuarios no puede borrarse.
Escribe el esquema relacional con la notación del curso y dibuja su grafo relacional.
Ver solución
PLANES (plan_id, nombre, precio_mensual)
- UK: nombre
- CHECK: precio_mensual > 0
USUARIOS (usuario_id, email, nombre, fecha_alta, telefono (N), plan_id)
- plan_id → PLANES(plan_id)
- UK: email
TITULOS (titulo_id, titulo, anio, duracion_min (N))
- CHECK: duracion_min > 0
VALORACIONES (*usuario_id*, *titulo_id*, puntuacion, fecha)
- usuario_id → USUARIOS(usuario_id) [ON DELETE CASCADE]
- titulo_id → TITULOS(titulo_id)
- CHECK: puntuacion BETWEEN 1 AND 5
flowchart RL
USUARIOS -->|plan_id| PLANES
VALORACIONES -->|"usuario_id (cascada)"| USUARIOS
VALORACIONES -->|titulo_id| TITULOS
Decisiones clave: la PK compuesta (usuario_id, titulo_id) de VALORACIONES garantiza que un usuario valore cada título una sola vez; plan_id es obligatorio (sin (N)) porque todo usuario tiene plan, y su FK es restringida, por lo que no se puede borrar un plan con usuarios.
Ejercicios propuestos
✏️ Ejercicio: Para
LINEAS_PEDIDO (pedido_id, num_linea, producto_id, cantidad, precio_unitario, descuento), cuya única clave candidata es{pedido_id, num_linea}, calcula cuántas superclaves tiene. (Solución: 2⁶⁻² = 16.)
✏️ Ejercicio: Escribe la tabla de verdad completa de
p AND (NOT q)para los nueve pares de valores (V, F, D) de p y q.
✏️ Ejercicio: Explica por qué la acción
SET NULLno se puede usar enLINEAS_PEDIDO.pedido_idaunque Oracle la soporte.
✏️ Ejercicio: Busca en el esquema EMPRESA una regla de negocio razonable que solo se pueda garantizar con una aserción o un disparador, y redáctala en lenguaje natural.
✏️ Ejercicio: Escribe el esquema relacional (con la notación del curso) de un taller mecánico con clientes, vehículos (matrícula única, cada vehículo de un cliente) y reparaciones (cada una de un vehículo, con fecha de entrada, fecha de salida opcional e importe). Dibuja su grafo relacional e indica el orden de creación de las tablas.
Resumen
| Concepto | Definición breve |
|---|---|
| Modelo relacional | Modelo lógico de Codd (1970): estructura (relaciones), integridad (restricciones) y manipulación (álgebra y cálculo) |
| Dominio | Conjunto con nombre de valores atómicos del mismo tipo |
| Atributo | Papel de un dominio en una relación (columna) |
| Relación | Subconjunto del producto cartesiano de sus dominios: r ⊆ D₁ × … × Dₙ |
| Tupla | Elemento de una relación (fila) |
| Grado / cardinalidad | Número de atributos / número de tuplas |
| Esquema / extensión | Estructura estática (intensión) / contenido en un instante (instancia) |
| Propiedades | Sin tuplas duplicadas, sin orden de tuplas ni de atributos, valores atómicos |
| Superclave | Conjunto de atributos que identifica de forma única cada tupla |
| Clave candidata | Superclave irreducible (unicidad + minimalidad) |
| Clave primaria / alternativa | Candidata elegida / candidatas restantes (UNIQUE) |
| Clave ajena | Atributos cuyos valores deben existir en la clave de otra relación o ser nulos |
| Nulo | Marca de ausencia de valor; las comparaciones con nulo dan desconocido (D) |
| Lógica trivaluada | V, F, D; AND = mínimo, OR = máximo, NOT = 1 − p; WHERE solo acepta V |
| Restricciones inherentes | Las impone el modelo (no duplicados, atomicidad, integridad de entidad) |
| Restricciones semánticas | Las define el diseñador (PK, UNIQUE, NOT NULL, FK, CHECK, aserciones) |
| Integridad de entidad | Ningún atributo de la clave primaria puede ser nulo |
| Integridad referencial | Toda FK coincide con una clave existente o es nula |
| Acciones referenciales | Restringida (NO ACTION/RESTRICT), cascada, puesta a nulos, valor por defecto |
| Oracle | Solo ON DELETE CASCADE y ON DELETE SET NULL; sin ON UPDATE ni SET DEFAULT |
CHECK | Condición sobre una tupla; rechaza solo si da F |
| Aserción | Condición global sobre varias tuplas o tablas (Oracle desde 26ai) |
| Disparador | Acción automática ante un evento (PL/SQL) |
| Reglas de Codd | Regla 0 + 12 reglas (1985) para evaluar si un SGBD es relacional |
| Grafo relacional | Nodos = relaciones, flechas = claves ajenas (de hija a padre) |