Fundamentos de Bases de Datos y SQL
Fundamentos de Bases de Datos y SQL
Tema 1 - Introducción
Nivel externo → Lo que ve el Esquema externo → Contiene los datos
Esq. Ext 1 Esq. Ext 2 … Esq. Ext n que el usuario puede ver (pueden no ser
usuario
todos)
Nivel conceptual → Estructura
de la base de datos Esquema conceptual → Describe los
Esq. Conc.
(Ej: Edad → int) atributos, clases asociaciones y
restricciones
Nivel interno → Esquema interno → Métodos de acceso y
Esq. Int.
Almacenamiento de datos organización de los archivos que almacena
la BD
Independencia lógica:
- Cambios en el esquema conceptual no afectan a los esquemas externos que no hagan referencia a las
clases, atributos o asociaciones modificadas (Ej: añadir un atributo no afecta a la vista).
- Cambio en un esquema externo no afectan a los otros esquemas, ni a los esquemas conceptual ni interno
(Ej: añadir/eliminar vistas no afecta a las vistas independientes a esta).
Independencia física:
- Cambios en el esquema interno no afecta a ninguno d ellos otros dos esquemas (Ej: cambio en el tamaño
de las páginas, métodos de acceso).
Reglas de integridad
- Regla de integridad de entidad: claves primarias únicas y sin valor NULL.
- Regla de integridad referencial: no puedes tener un valor en una foreign key (atributo de una tabla que
referencia a otro de otra tabla) que no exista en la tabla.
- Restrict → No permite borrar o modificar la clave primaria referenciada en alguna foreign key.
- Cascade → Cuando se borra o modifica una clave primaria referenciada en alguna foreign key se
borran o modifican todas las referencias.
- Anulación → Al borrar o modificar una clave primaria referenciada en alguna foreign key, se
ponen a NULL todas las referencias.
- Regla de integridad de dominio: respetar el tipo de valor (Ej: integer → introducir un int).
1
Bases de Datos
UPDATE <tabla>
SET <col> = {expressión/ NULL} [,<col> = {expressión/ NULL}...]
WHERE <condiciones> ;
No repite atributo (Solo poner si se repiten las consultas)
SELECT [DISTINCT | ALL] <columnas_que_seleccionar> [,<funciones_de_agregación>]
FROM <tabla_que_consultar>
[ WHERE <condiciones> ]
ORDER BY <columna> [ DESC | ASC ], … Si tienen el mismo primer
atributo repetido ordena
GROUP BY <columnas_segun_las_que_agrupar>
HAVING <condiciones_para_grupos>; según el criterio seleccionado
2
Bases de Datos
3
Bases de Datos
Asociaciones ternarias:
min .. max min .. max 0 .. 1 0 .. 1
A B Aula Se hace clase Grupo
min .. max *
C Horario
A(atributoa_primary_key, …)
B(atributob_primary_key, … )
4
Bases de Datos
C(atributoc_primary_key, … )
NUEVA_RELACION(atributoa_primary_key, atributob_primary_key, atributoc_primary_key)
donde {atributoa_primary_key} referencia A,
{atributob_primary_key} referencia B y
{atributoc_primary_key} referencia C
Transformaciones de asociaciones ternarias: muchos-muchos-muchos → La foreign key de la nueva relación
esta formada por las claves de las tres clases.
Transformaciones de asociaciones ternarias: muchos-muchos-uno → La foreign key de la nueva relación está
formada por las claves de las dos clases de los “muchos” (*) de la asociación.
Transformaciones de asociaciones ternarias: muchos-uno-uno → La foreign key de la nueva relación está
formada por la clave de “muchos” y una de las otras dos claves (escoger la que se quiera).
Asociaciones recursivas:
A Persona 0 .. 1 esposa
*
0 .. 1 0 .. 1 Persona Fecha
min .. max min .. max madre Es madre de hijo Se ha casado con
0 .. 1 esposo
La multiplicidad (min .. max) de clase dentro de una asociación indica cuántas instancias de esa clase pueden
asociarse con las otras clases de la asociación.
- 0 .. 1 → Sin instancia o sólo una (opcional)
- 1 → Una y siempre una instancia (obligatorio)
- * → Cero o múltiples instancias (opcional)
- 1 .. * → Múltiples instancias, pero al menos una (obligatorio)
5
Bases de Datos
BEGIN
-- Sentencia de asignación
nombre_variable := (SELECT atr FROM tabla WHERE condicion);
RETURN variable_retorno;
END;
$$LANGUAGE plpgsql;
-- OPCION 1
-- El SETOF devuelve un conjunto de tuplas especificadas en el CREATE TYPE
CREATE FUNCTION nom_proc(param_entrada tipus) RETURNS SETOF conjunto AS $$
...
/* Va devolviendo a cada ejecución los valores de la variable.
El procedimiento acaba cuando se ejecuta un RETURN sin NEXT o llega al final */
RETURN NEXT variable;
...
END;
$$LANGUAGE plpgsql;
-- OPCION 2
CREATE FUNCTION nom_proc(param_entrada tipus) RETURNS conjunto AS $$
DECLARE
conj conjunto;
var tipo_var;
BEGIN
...
conj.var1 := var;
...
RETURN conj;
END;
$$LANGUAGE plpgsql;
-- SENTENCIAS CONDICIONALES
IF (condicion) THEN Bloque de sentencias;
ELSE IF (condicion) THEN Bloque de sentencias;
ELSE THEN Bloque de sentencias;
END IF;
6
Bases de Datos
-- SENTENCIAS ITERATIVAS
-- Por cada statement ; al final
FOR var IN sentenciaSQL
LOOP statements END LOOP;
-- GESTIÓN DE ERRORES
CREATE FUNCTION proc() RETURNS tipo_var AS $$
DECLARE
missatge missatgesExcepcions.texte%TYPE;
BEGIN
IF (condicion_error) THEN
SELECT texte INTO missatge FROM missatgesExcepcions WHERE num = 1;
RAISE EXCEPTION '%', missatge;
END IF;
EXCEPTION
WHEN raise_exception THEN RAISE EXCEPTION '%', SQLERRM;
WHEN others THEN -- Gestiona otros errores
SELECT texte INTO missatge FROM missatgesExcepcions WHERE num = 2;
RAISE EXCEPTION '%',missatge;
END;
$$ LANGUAGE plpgsql;
-- DISPARADORES
CREATE FUNCTION nomFunc() RETURNS trigger AS $$
DECLARE
var var_type;
BEGIN
-- Ejemplo de cómo usar NEW (válido para OLD) para consultar el nuevo/viejo atributo
SELECT * INTO var FROM table WHERE atr = NEW.atr1;
...
RETURN {NEW | OLD | NULL};
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER nombre {BEFORE | AFTER} {INSERT | DELETE | UPDATE [OF columna, ...]}
ON tabla [FOR [EACH] {ROW | STATEMENT}]
EXECUTE PROCEDURE nomFunc;
/* FOR EACH ROW -> Se ejecuta para cada tupla de una tabla en una sentencia SQL
FOR EACH STATEMENT -> Se ejecuta 1 vez por cada sentencia SQL */
ROW STATEMENT
RETURN NEW → INSERT, UPDATE → Se ejecuta la
sentencia con el valor modificado
RETURN OLD → DELETE, UPDATE (sin el cambio hecho RETURN NULL → Ignoramos
BEFORE
en la sentencia) el valor devuelto
RETURN NULL → No ejecuta la sentencia que activa el
disparador
RETURN NULL → Ignoramos
AFTER RETURN NULL → Ignoramos el valor devuelto
el valor devuelto
7
Bases de Datos
Actualización perdida: se Lectura no confirmada: se Lectura no repetible: se produce Análisis inconsistente: cuando a Fantasmas: una transacción lee
produce cuando intentamos produce cuando una transacción si una transacción lee 2 veces el mitad de una ejecución de una un conjunto de datos
escribir/actualizar mediante una lee un dato que se ha modificado mismo dato y obtiene valores transacción, otra transacción relacionado y existe otra
operación, pero esta no se por otra transacción que después diferentes, debido a una cambia el estado de una variable. transacción que añade nuevos
produce. aborta. modificación efectuada por otra datos que pertenecen a ese
transacción. conjunto.
T1 T2 T1 T2 T1 T2 T1 T2 T1 T2
RU(A) RU(A) R(A) R(A) R(IC)
RU(A) W(A) RU(A) RU(B) R(C1)
W(A) RU(A) W(A) W(B) R(C2)
W(A) W(A) R(A) R(B) RU(C3)
COMMIT COMMIT COMMIT RU(A) W(C3)
COMMIT ABORT COMMIT W(A) RU(IC)
COMMIT W(IC)
COMMIT R(IC)
R(C1)
R(C2)
R(C3)
A A A IC
T1 T2 T1 T2 T1 T2 T1 T2 T1 T2
A A A B IC, C3
READ UNCOMMITED READ UNCOMMITED READ UNCOMMITED READ UNCOMMITED READ UNCOMMITED
READ COMMITED READ COMMITED READ COMMITED READ COMMITED READ COMMITED
REPEATABLE READ REPEATABLE READ REPEATABLE READ REPEATABLE READ REPEATABLE READ
SERIALIZABLE SERIALIZABLE SERIALIZABLE SERIALIZABLE SERIALIZABLE
8
Bases de Datos
La teoría de la serializabilidad define las condiciones que se han de cumplir para que las transacciones estén
aisladas entre sí correctamente.
- Gránulos: las transacciones están formadas por acciones (operaciones) sobre datos elementales llamados
gránulos (página (bloque) del disco, un registro (una tupla), etc). Operaciones sobre gránulos:
• R(G): Lectura del gránulo G. (Sentencia SQL: SELECT)
• RU(G): Lectura con intención de modificación posterior del gránulo G. Sentencias SQL:
• W(G): Escritura del gránulo G. INSERT/UPDATE/DELETE
- Horario o historia: dónde se guarda el orden de las acciones dentro de cada transacción.
- Horario serial: cuando las transacciones se ejecutan completamente una detrás de otra sin solaparse.
- Acciones conflictivas o no conmutables: dos acciones serán conflictivas cuando 2 transacciones distintas
operan sobre el mismo gránulo y al menos una de las acciones es de escriptura.
- Grafo de precedencias
- Horario serializable: es un horario serializable aquel que al construir el grafo no tiene ciclos.
Técnicas de control de concurrencia: permite resolver las interferencias entre transacciones de dos maneras:
- Cancelando automáticamente las transacciones problemáticas y deshaciendo sus cambios.
- Suspendiendo la ejecución temporalmente y volviéndola a ejecutar cuando no haya peligro de
interferencia.
Control de concurrencia con reservas: se reserva un gránulo con una cierta modalidad antes de efectuar una
acción.
T1 T2
- LOCK(G, S): permite al gránulo G lecturas (modalidad compartida)
LOCK(A, S)
- LOCK(G, X): permite al gránulo G hacer lecturas y escrituras (modalidad
R(A)
exclusiva: ninguna otra transacción pueda hacer un LOCK del gránulo G
hasta que este no se libere). LOCK(A, X)
- UNLOCK(G): liberamos la reserva sobre el gránulo G. LOCK(B, S) ·
R(B) ·
En ciertos momentos es conveniente baja el nivel de aislamiento y dejar
que se produzcan interferencias: UNLOCK(A) ·
RU(A)
- READ UNCOMMITED: evita que cualquier otra transacción se actualice
W(A)
hasta que acabe la transacción.
- READ COMMITED: impide que otra transacción lea datos que aún no se UNLOCK(B)
han confirmado. UNLOCK(A)
- REPEATABLE READ: hasta que no acabe la transacción, impide que otra COMMIT
transacción un dato ya leído. COMMIT
- SERIALIZABLE: aislamiento total excepto fantasmas.
Recuperación:
- Restauración: garantiza que la base de datos cumplan la atomicidad de las transacciones.
- Reconstrucción: recuperan el estado de la BD cuando se produce un pérdida total o parcial.
• Reconstrucción hacia delante: implica deshacer los cambios de una transacción abortada.
• Reconstrucción hacía atrás: implica rehacer los cambios de una transacción confirmada.
9
Bases de Datos
Ficheros: es la unidad global a partir de la cual el SO gestiona los datos en los discos magnéticos.
Es un conjunto de extensiones.
Extensión: es la unidad de adquisición de espacio por cada fichero. (es un múltiplo entero de la
página). Es el nombre de páginas consecutivas que el SO adquiere a petición de la SGBD cuando esta
detecta que necesita más espacio para un fichero determinado
Página: es el componente físico más pequeño, contiene y almacena los datos a nivel lógico. Hay 2
formas de ver el concepto de página:
- Unidad discreta de tranporte de datos (E/S) entre la memoria externa (disco) y la memoria
interna. En SO normalmente bloque.
- Unidad de organización de datos almacenados. El espacio de disco se estructura en un
nombre múltiple de páginas, y cada página se puede direccionar individualmente.
La estructura física sigue una longitud fija (2K, 4K, 8K)
Espacio libre
5 4 3 2 1
nos dice si es null / not null (si el campo admite valores nulos)
y contiene la longitud del campo.
10
Bases de Datos
A nivel virtual también existe un sistema de paginación que se hace de manera paralela a la física.
Correspondencia entre páginas reales y páginas virtuales:
a. Nivel virtual
Núm. página 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
b. Nivel físico
Extensión 1 Extensión 1
Fichero 1 Extensión 2
Fichero 2 Extensión 2
- Nivel lógico
Los métodos de acceso nos permiten la lectura o actualización de una tabla, dado que cuando leemos o
actualizamos un dato accedemos a la paginación virtual y de esta a la física. Los siguientes métodos de acceso:
- Acceso por posición:
• Directo
INSERT INTO x VALUES (a, b, c, d);
1 2 3 4 5 6 7 8 9 10
• Secuencial
SELECT * FROM x
1 2 3 4 5 6 7 8 9 10
Se usan índices para una implementación más eficiente, porque ocupan menos espacio que los datos.
Funcionan de manera similar a los índices de los libros. Y hacen el acceso por valor vía acceso por
posición.
Ínidce (valor, RID)
Datos
fila
Árboles B+: es una de las maneras de estructurar los índices. Un árbol de orden d (d-ario) tiene como mucho 2d
valores y 2d + 1 apuntadores. Ejemplo:
11
Bases de Datos
mejor rendimiento:
- Todos los nodos han de estar llenos como mínimo al 50%, menos la raíz.
- Todas las hojas han de estar al mísmo nivel.
Cada nodo se almacena en una página → Para acceder a una hoja harán falta n niveles.
Ejercicio: quantas filas/registros se podrían indexar en un árbol de orden 𝒅 y lleno al 𝒙 %:
- Nivel 1: 1 nodo con 𝑥 valores y 𝑥 + 1 apuntadores.
- Nivel 2: 𝑥 + 1 nodos con 𝑥 valores y 𝑥 + 1 apuntadores cada uno.
- Nivel 3: (𝑥 + 1)2 nodos con 𝑥 valores y 𝑥 + 1 apuntadores cada uno. (si parasemos → (𝑥 + 1)2 ∗ 𝑥 filas)
- Nivel 4: (𝑥 + 1)3 nodos con 𝑥 entradas → (𝑥 + 1)3 ∗ 𝑥 filas/entradas/registros.
Para saber la altura de un árbol: log 𝑥+1 𝑛º 𝑓𝑖𝑙𝑎𝑠/𝑒𝑛𝑡𝑟𝑎𝑑𝑎𝑠/𝑟𝑒𝑔𝑖𝑠𝑡𝑟𝑜𝑠
Índices agrupados (clústers): es aquel en que los datos que indexa estan ordenados físicamente a partir del
acceso secuencial por valor que proporciona. Esto supone que hay que mantener un orden físico, para ello se
deja un % de espacio libre en las páginas, si se llenan se llenan páginas excedentes encadenadas y en el caso de
haber un % elevado de éstas, se regrupan.
Accesos por diversos valores: accesos directos
- Estrategia de intersección de RIDs: uso de estructuras de árboles B+, para crear conjuntos con las
condiciones y devuelve la intersección de los conjuntos.
- Estrategia de índice multi-atributo: uso de estructura de árboles B+, el resultado lo llamamos lista y
establecemos un orden lineal entre las listas, de esta manera se ordenan según la primera condición, de las
que cumplen la primera condición se ordenan según la segunda…
Accesos por diversos valores: accesos secuenciales y mixtos:
[x, y]
- Estrategia de índice multi-atributo (rango)
- Estrategia de índice multi-atributo multi-dimensional: no sigue un
<< <>= >=< >=>=
orden lineal
Creación de un índice CREATE INDEX nom_indice ON tabla(atr)
Para un índice descendiente CREATE INDEX nom_indice ON tabla(atr DESC)
Índice agrupado CREATE INDEX CLUSTER nom_indice ON tabla(atr)
Índice sin valores repetidos CREATE UNIQUE INDEX nom_indice ON tabla(atr)
Índice multi-atributo CREATE INDEX nom_indice ON tabla(atr1, atr2)
12
Bases de Datos
13
Bases de Datos
// ResultSet
// Transacciones
c.commit(); // Guarda permanentemente los cambios hechos
c.rollback(); // Deshace los cambios que no se hayan ya guardado en la BD
/* Excepciones (así es como se crea una clase para programar con SQL) */
public class progrEx1 {
public static void main (String[] args) {
try {
// Enregistrar el driver
// Conexión a la base de datos
// Consultes-modificaciones
// Desconexión
}
catch (ClassNotFoundException ce) {
System.out.println ("Error al cargar el driver d'informix.");
}
catch (SQLException se) {
System.out.println ("Error conexión o acceso a la base de
datos");}
}}
// Gestión de errores
try {
// Ejecutar el Statement o PreparedStatement
} catch (SQLException se) {
if (se.getSQLState().equals("Código")) System.out.println("Error que sea");
else System.out.println(se.getSQLState() + " " + se.getMessage())
14