1.1 Bases de datos y SQL¶
Qué es una base de datos¶
Una base de datos es un conjunto de información organizada para poder guardarla, buscarla y modificarla de forma rápida y segura. El programa que la gestiona se llama sistema gestor de bases de datos (SGBD): MySQL, PostgreSQL, Oracle, SQL Server o SQLite son ejemplos.
Podrías guardar los datos de un instituto en una hoja de cálculo, pero enseguida aparecen problemas: datos repetidos (el nombre de un grupo escrito cien veces, con erratas), imposibilidad de que varias personas modifiquen a la vez sin pisarse, y ninguna garantía de que los datos tengan sentido (una nota de 25, un alumno en un grupo que no existe). Una base de datos relacional resuelve esto.
El modelo relacional¶
En una base de datos relacional la información se guarda en tablas, y las tablas se relacionan entre sí.
| Concepto | Qué es | Ejemplo |
|---|---|---|
| Tabla | Un conjunto de datos del mismo tipo | alumnos |
| Fila (registro, tupla) | Un elemento concreto | el alumno «Ana Gil» |
| Columna (campo, atributo) | Un dato de cada fila, con un tipo | nombre, ciudad, nacimiento |
| Clave primaria | La columna (o columnas) que identifica cada fila de forma única | alumnos.id |
| Clave foránea | Una columna que apunta a la clave primaria de otra tabla y las relaciona | alumnos.id_grupo → grupos.id |
| NULL | La ausencia de valor («no se sabe» o «no tiene») | un alumno sin grupo |
Gracias a las claves foráneas, el nombre de un grupo se guarda una sola vez y los alumnos solo guardan su número. Si el grupo cambia de nombre, se cambia en un único sitio.
No es la única forma de guardar datos
Existen también las bases de datos no relacionales (NoSQL), que no usan tablas unidas por claves sino documentos, pares clave-valor, columnas o grafos. Son una buena elección para otros problemas (datos que cambian de forma, enormes cantidades de usuarios, redes de relaciones), pero para datos con muchas reglas y relaciones, como los de un instituto, la relacional sigue siendo lo habitual. Verás las diferencias con ejemplos en la unidad 7.
SQL: un lenguaje declarativo¶
SQL (Structured Query Language) no se escribe como un programa paso a paso. Es declarativo: describes qué datos quieres y el gestor decide cómo obtenerlos (ver la diferencia con el enfoque imperativo en la web de Android).
Las sentencias se agrupan según lo que hacen:
| Familia | Para qué | Sentencias |
|---|---|---|
| DQL (consulta) | Leer datos | SELECT |
| DML (manipulación) | Cambiar datos | INSERT, UPDATE, DELETE |
| DDL (definición) | Crear y cambiar la estructura | CREATE, ALTER, DROP |
| TCL (transacciones) | Agrupar y confirmar cambios | BEGIN, COMMIT, ROLLBACK |
| DCL (control) | Dar o quitar permisos | GRANT, REVOKE |
La base de datos de ejemplo: un instituto¶
Todos los ejemplos y ejercicios de esta web usan la misma base de datos, con datos ficticios:
grupos (id, nombre, curso)
│ 1
│ N
alumnos (id, nombre, apellido, nacimiento, ciudad, id_grupo) ──┐
│ 1 │
│ N │
notas (id_alumno, id_asignatura, nota, convocatoria) │
│ N │
│ 1 │
asignaturas (id, nombre, horas, id_profesor) │
│ N │
│ 1 │
profesores (id, nombre) │
- Un grupo tiene muchos alumnos.
- Un alumno tiene muchas notas (una por asignatura y convocatoria), y una asignatura aparece en muchas notas: entre alumnos y asignaturas hay una relación de muchos a muchos, que se resuelve con la tabla
notas. - Una asignatura la imparte un profesor (o ninguno todavía).
- Hay un alumno sin grupo y una asignatura sin profesor, a propósito, para practicar con
NULL.
Estas son las tablas pequeñas completas:
SELECT * FROM grupos;
Resultado:
| id | nombre | curso |
|---|---|---|
| 1 | 1DAM-A | 1 |
| 2 | 1DAM-B | 1 |
| 3 | 2DAM-A | 2 |
3 filas
SELECT * FROM asignaturas;
Resultado:
| id | nombre | horas | id_profesor |
|---|---|---|---|
| 1 | Programación | 230 | 1 |
| 2 | Bases de Datos | 160 | 2 |
| 3 | Entornos de Desarrollo | 100 | 3 |
| 4 | Lenguajes de Marcas | 100 | 3 |
| 5 | Sistemas Informáticos | 160 | 4 |
| 6 | Inglés Técnico | 60 | NULL |
6 filas
Y esta es la tabla de alumnos (los 10 primeros de 14):
SELECT * FROM alumnos;
Resultado:
| id | nombre | apellido | nacimiento | ciudad | id_grupo |
|---|---|---|---|---|---|
| 1 | Ana | Gil | 2005-03-14 | Cádiz | 1 |
| 2 | Luis | Romero | 2004-11-02 | Sevilla | 1 |
| 3 | Marta | Díaz | 2005-07-21 | Cádiz | 1 |
| 4 | Pablo | Núñez | 2003-01-30 | Jerez | 2 |
| 5 | Sara | Vega | 2005-09-09 | Sevilla | 2 |
| 6 | Iván | Torres | 2004-05-17 | Cádiz | 2 |
| 7 | Elena | Marín | 2002-12-05 | Málaga | 3 |
| 8 | Raúl | Campos | 2003-06-25 | Cádiz | 3 |
| 9 | Noa | Prieto | 2004-02-11 | Jerez | 3 |
| 10 | Dani | Soto | 2005-04-01 | Sevilla | 1 |
| … | … | … | … | … | … |
14 filas (se muestran 10)
Cómo practicar¶
Necesitas un sitio donde escribir SQL y ejecutarlo. Cualquiera de estos sirve:
| Opción | Cuándo |
|---|---|
SQLite (programa sqlite3 o un visor como DB Browser for SQLite) |
La más sencilla: un solo archivo, sin servidor. Es el motor con el que se han comprobado todos los resultados de esta web |
| MySQL / MariaDB con MySQL Workbench o DBeaver | Si tu módulo usa MySQL |
| PostgreSQL con pgAdmin o DBeaver | Si prefieres PostgreSQL |
Para crear la base de datos en tu herramienta, copia este script y ejecútalo entero una vez:
Script para crear y rellenar la base de datos del instituto
CREATE TABLE grupos (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL,
curso INTEGER NOT NULL
);
CREATE TABLE profesores (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL
);
CREATE TABLE asignaturas (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL,
horas INTEGER NOT NULL,
id_profesor INTEGER REFERENCES profesores(id)
);
CREATE TABLE alumnos (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL,
apellido TEXT NOT NULL,
nacimiento TEXT NOT NULL,
ciudad TEXT NOT NULL,
id_grupo INTEGER REFERENCES grupos(id)
);
CREATE TABLE notas (
id_alumno INTEGER NOT NULL REFERENCES alumnos(id),
id_asignatura INTEGER NOT NULL REFERENCES asignaturas(id),
nota REAL NOT NULL,
convocatoria INTEGER NOT NULL DEFAULT 1,
PRIMARY KEY (id_alumno, id_asignatura, convocatoria)
);
INSERT INTO grupos VALUES
(1, '1DAM-A', 1),
(2, '1DAM-B', 1),
(3, '2DAM-A', 2);
INSERT INTO profesores VALUES
(1, 'Marta Ruiz'),
(2, 'Pedro Salas'),
(3, 'Lucía Ferrer'),
(4, 'Hugo Navas');
INSERT INTO asignaturas VALUES
(1, 'Programación', 230, 1),
(2, 'Bases de Datos', 160, 2),
(3, 'Entornos de Desarrollo', 100, 3),
(4, 'Lenguajes de Marcas', 100, 3),
(5, 'Sistemas Informáticos', 160, 4),
(6, 'Inglés Técnico', 60, NULL);
INSERT INTO alumnos VALUES
(1, 'Ana', 'Gil', '2005-03-14', 'Cádiz', 1),
(2, 'Luis', 'Romero', '2004-11-02', 'Sevilla', 1),
(3, 'Marta', 'Díaz', '2005-07-21', 'Cádiz', 1),
(4, 'Pablo', 'Núñez', '2003-01-30', 'Jerez', 2),
(5, 'Sara', 'Vega', '2005-09-09', 'Sevilla', 2),
(6, 'Iván', 'Torres', '2004-05-17', 'Cádiz', 2),
(7, 'Elena', 'Marín', '2002-12-05', 'Málaga', 3),
(8, 'Raúl', 'Campos', '2003-06-25', 'Cádiz', 3),
(9, 'Noa', 'Prieto', '2004-02-11', 'Jerez', 3),
(10, 'Dani', 'Soto', '2005-04-01', 'Sevilla', 1),
(11, 'Lola', 'Ortiz', '2003-08-19', 'Málaga', 2),
(12, 'Marcos', 'Peña', '2002-10-10', 'Cádiz', 3),
(13, 'Irene', 'Lara', '2005-12-24', 'Jerez', NULL),
(14, 'Álex', 'Roca', '2004-03-03', 'Sevilla', 2);
INSERT INTO notas VALUES
(1, 1, 3.5, 1),
(1, 1, 5.5, 2),
(1, 2, 6.0, 1),
(1, 3, 9.0, 1),
(1, 4, 3.0, 1),
(1, 4, 4.0, 2),
(2, 1, 7.0, 1),
(2, 2, 6.5, 1),
(2, 3, 8.0, 1),
(2, 4, 6.5, 1),
(3, 1, 8.0, 1),
(3, 2, 8.0, 1),
(3, 3, 8.0, 1),
(3, 4, 7.0, 1),
(4, 1, 4.5, 1),
(4, 1, 7.0, 2),
(4, 2, 3.5, 1),
(4, 2, 6.5, 2),
(4, 3, 6.0, 1),
(4, 4, 8.5, 1),
(5, 1, 7.5, 1),
(5, 2, 7.5, 1),
(5, 3, 4.0, 1),
(5, 3, 5.5, 2),
(5, 4, 9.5, 1),
(6, 1, 9.5, 1),
(6, 2, 8.5, 1),
(6, 3, 10.0, 1),
(6, 4, 6.0, 1),
(7, 2, 3.0, 1),
(7, 2, 4.5, 2),
(7, 5, 6.5, 1),
(7, 6, 4.5, 1),
(7, 6, 6.5, 2),
(8, 2, 9.0, 1),
(8, 5, 7.5, 1),
(8, 6, 6.5, 1),
(9, 2, 2.5, 1),
(9, 2, 5.0, 2),
(9, 5, 5.0, 1),
(9, 6, 5.5, 1),
(10, 1, 5.5, 1),
(10, 2, 7.0, 1),
(10, 3, 6.0, 1),
(10, 4, 3.5, 1),
(10, 4, 5.5, 2),
(11, 1, 8.0, 1),
(11, 2, 7.0, 1),
(11, 3, 6.0, 1),
(11, 4, 9.0, 1),
(12, 2, 4.5, 1),
(12, 2, 6.5, 2),
(12, 5, 9.5, 1),
(12, 6, 6.0, 1),
(14, 1, 6.5, 1),
(14, 2, 2.5, 1),
(14, 2, 3.5, 2);
Si tu motor no es SQLite
El SQL básico (SELECT, WHERE, JOIN, GROUP BY...) es casi idéntico en todos los motores. Donde hay diferencias (funciones de fecha, concatenación de texto, LIMIT...) se indica en un recuadro como este, y hay una tabla de diferencias entre motores.
Escribir SQL: normas básicas¶
- Cada sentencia termina en punto y coma (
;). - Las palabras clave (
SELECT,FROM...) no distinguen mayúsculas de minúsculas, pero por costumbre se escriben en mayúsculas para distinguirlas de los nombres. - Los textos van entre comillas simples:
'Cádiz'. Las comillas dobles se reservan para nombres de tablas o columnas con caracteres especiales. - Los comentarios son
-- hasta el final de la líneao/* varias líneas */. - Puedes repartir una sentencia en varias líneas: SQL ignora los saltos de línea y los espacios.
-- Los alumnos de Cádiz
SELECT nombre, apellido
FROM alumnos
WHERE ciudad = 'Cádiz';