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 CHECK en 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} y D_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 localidad como 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).
  • telefonos contiene una lista de valores: no es atómico.
  • (Un tercer problema, más sutil: si emp_id es 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 de oficio sobre EMPLEADOS da 11 tuplas (sin repetidos). Para obtener lo mismo en SQL necesitas SELECT 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ón uq_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 DEPARTAMENTOS con la clave {dept_id} (n = 4, k = 1) habría 2³ = 8 superclaves… si no fuera porque nombre tambié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 el nif de 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:

  1. Los atributos de FK tienen los mismos dominios que los de la clave referenciada de R₁ (y el mismo número de atributos).
  2. 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_id es clave ajena que referencia DEPARTAMENTOS.dept_id. El empleado 120 tiene dept_id = 30 y existe el departamento 30: correcto. El empleado 160 tiene dept_id nulo (becario sin departamento): también correcto. Un empleado con dept_id = 99 violarí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_id y PEDIDOS.empleado_id referencian EMPLEADOS(emp_id).
  • Puede formar parte de la clave primaria: LINEAS_PEDIDO.pedido_id es a la vez parte de la PK y clave ajena hacia PEDIDOS. En ASIGNACIONES, 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 (PEDIDOS tiene cliente_id → CLIENTES y empleado_id → EMPLEADOS).
  • Puede admitir nulos o no, según la obligatoriedad de la participación en el modelo conceptual: PEDIDOS.cliente_id es obligatoria (todo pedido es de un cliente), PEDIDOS.empleado_id es 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 = 0 y Carmen Ruiz (110) tiene comision = 500, mientras que Raquel Molina (121) tiene comision = 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. Incluso NULL = NULL da D: dos valores desconocidos no tienen por qué ser iguales.
  • Cualquier operación aritmética con un nulo da nulo: salario + NULL es NULL.
  • Para preguntar si algo es nulo se usan predicados especiales que siempre devuelven V o F: IS NULL e IS 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 WHERE de 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 < 500 sobre 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 y COUNT(columna) cuenta valores no nulos.
  • NOT IN con una subconsulta que devuelve algún nulo produce resultado vacío, porque x NOT IN (a, NULL) equivale a x <> 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 como NULL, a diferencia de lo que dice el estándar.
  • Las restricciones CHECK funcionan al revés que el WHERE: rechazan la fila solo si la condición es F. Si es D, la fila se acepta. Por eso CHECK (comision >= 0) no impide que comision sea 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 con pedido_id nulo ni con num_linea nulo. Y solo se aplica a la clave primaria: las claves alternativas sí pueden admitir nulos (en Oracle, una columna UNIQUE puede tener varias filas con NULL), salvo que además las declares NOT 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 ACTION y RESTRICT en el estándar es de momento de comprobación: RESTRICT comprueba inmediatamente, antes de hacer nada; NO ACTION comprueba 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_id tiene ON DELETE CASCADE. Si borras el pedido 5001, se borran automáticamente sus 3 líneas. Si PEDIDOS.cliente_id también tuviera ON 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 UPDATE ni SET 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 NULL si el atributo es obligatorio.
  • CHECK con 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 CHECK solo rechaza la fila si la condición es F. El pedido 5022 tiene fecha_envio nula: NULL >= fecha_pedido da 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.sql borra 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 email 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) y CATEGORIAS.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.
  • EMPLEADOS es la relación más referenciada: la referencian EMPLEADOS, CLIENTES, PEDIDOS y ASIGNACIONES, con cuatro papeles distintos (jefe, comercial, gestor del pedido, miembro de proyecto).
  • LINEAS_PEDIDO y ASIGNACIONES tienen 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 con UNIQUE.

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 pedidos contiene 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 NULL no se puede usar en LINEAS_PEDIDO.pedido_id aunque 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)