💾 ¿Qué es una Base de Datos?
📖 Definición
Una Base de Datos (Database, DB) es una colección sistemáticamente estructurada de datos. Un DBMS (Database Management System, Sistema de Gestión de Bases de Datos) es el software que crea, gestiona y accede a las bases de datos. Las bases de datos permiten el almacenamiento y recuperación eficiente de datos, permitiendo que múltiples usuarios accedan de forma segura y simultánea.
🎯 Comprender con Analogía
Sistema de Biblioteca
Piensa en una base de datos como una biblioteca:
- Base de Datos: La biblioteca completa
- Tabla: Cada sección (ficción, ciencia, historia, etc.)
- Fila (Row): Libro individual
- Columna (Column): Atributos del libro (título, autor, año de publicación, etc.)
- Clave Primaria (Primary Key): Número único del libro
- DBMS: Bibliotecario y sistema de gestión
Biblioteca (Base de Datos)
├─ Sección Ficción (Tabla)
│ ├─ Libro 1: Harry Potter, J.K. Rowling, 1997
│ ├─ Libro 2: El Señor de los Anillos, Tolkien, 1954
│ └─ Libro 3: El Principito, Saint-Exupéry, 1943
├─ Sección Ciencia (Tabla)
│ ├─ Libro 1: Cosmos, Carl Sagan, 1980
│ └─ Libro 2: El Gen Egoísta, Richard Dawkins, 1976
└─ Registro de Préstamos (Tabla)
├─ Registro 1: Miembro123, Harry Potter, 2024-01-15
└─ Registro 2: Miembro456, Cosmos, 2024-01-20
⚙️ Cómo Funciona
1. Estructura de Base de Datos
Base de Datos (Database)
└─ Tabla (Table)
├─ Fila (Row/Record) - Elemento de datos individual
│ └─ Ejemplo: Información de un usuario
└─ Columna (Column/Field) - Atributos de datos
└─ Ejemplo: Nombre, email, edad
2. Ejemplo de Base de Datos Relacional
-- Tabla users
users
┌────┬────────┬──────────────────┬─────┐
│ id │ name │ email │ age │
├────┼────────┼──────────────────┼─────┤
│ 1 │ Juan │ juan@mail.com │ 25 │
│ 2 │ María │ maria@mail.com │ 30 │
│ 3 │ Pedro │ pedro@mail.com │ 28 │
└────┴────────┴──────────────────┴─────┘
-- Tabla orders
orders
┌────┬─────────┬─────────────┬───────┐
│ id │ user_id │ product │ price │
├────┼─────────┼─────────────┼───────┤
│ 1 │ 1 │ Portátil │ 1500 │
│ 2 │ 1 │ Ratón │ 30 │
│ 3 │ 2 │ Teclado │ 80 │
└────┴─────────┴─────────────┴───────┘
↑
└─ Clave foránea: Referencias id en tabla users
3. Operaciones CRUD
CRUD son las 4 operaciones básicas de base de datos:
C - Create (Crear): Añadir nuevos datos
R - Read (Leer): Consultar datos
U - Update (Actualizar): Cambiar datos existentes
D - Delete (Eliminar): Borrar datos
💡 Ejemplos Reales
CRUD con SQL
-- CREATE (Crear): Crear tabla
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- CREATE (Crear): Añadir datos
INSERT INTO users (name, email, age)
VALUES ('Juan', 'juan@mail.com', 25);
INSERT INTO users (name, email, age)
VALUES
('María', 'maria@mail.com', 30),
('Pedro', 'pedro@mail.com', 28);
-- READ (Leer): Consultar todos los usuarios
SELECT * FROM users;
-- READ (Leer): Consulta condicional
SELECT name, email FROM users
WHERE age >= 28;
-- READ (Leer): Consulta ordenada
SELECT * FROM users
ORDER BY age DESC;
-- READ (Leer): Búsqueda
SELECT * FROM users
WHERE name LIKE 'Juan%';
-- UPDATE (Actualizar): Modificar datos
UPDATE users
SET age = 26
WHERE name = 'Juan';
-- UPDATE (Actualizar): Modificar múltiples campos
UPDATE users
SET email = 'new@mail.com', age = 31
WHERE id = 2;
-- DELETE (Eliminar): Borrar datos
DELETE FROM users
WHERE id = 3;
-- DELETE (Eliminar): Eliminación condicional
DELETE FROM users
WHERE age < 20;
Uso de Base de Datos en Node.js
const mysql = require('mysql2/promise');
// Conexión a base de datos
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10
});
// CREATE - Añadir usuario
async function createUser(name, email, age) {
const [result] = await pool.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
console.log('ID creado:', result.insertId);
return result.insertId;
}
// READ - Obtener todos los usuarios
async function getAllUsers() {
const [rows] = await pool.execute('SELECT * FROM users');
return rows;
}
// READ - Obtener usuario específico
async function getUserById(id) {
const [rows] = await pool.execute(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0];
}
// UPDATE - Actualizar información de usuario
async function updateUser(id, name, email, age) {
const [result] = await pool.execute(
'UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?',
[name, email, age, id]
);
console.log('Filas actualizadas:', result.affectedRows);
return result.affectedRows;
}
// DELETE - Eliminar usuario
async function deleteUser(id) {
const [result] = await pool.execute(
'DELETE FROM users WHERE id = ?',
[id]
);
console.log('Filas eliminadas:', result.affectedRows);
return result.affectedRows;
}
// Ejemplo de uso
async function main() {
try {
// Crear
const userId = await createUser('Juan', 'juan@mail.com', 25);
// Consultar
const users = await getAllUsers();
console.log('Todos los usuarios:', users);
// Consultar usuario específico
const user = await getUserById(userId);
console.log('Usuario específico:', user);
// Actualizar
await updateUser(userId, 'Juan', 'new@mail.com', 26);
// Eliminar
await deleteUser(userId);
} catch (error) {
console.error('Error:', error);
}
}
main();
Uso de ORM (Sequelize)
const { Sequelize, DataTypes } = require('sequelize');
// Conexión a base de datos
const sequelize = new Sequelize('myapp', 'root', 'password', {
host: 'localhost',
dialect: 'mysql'
});
// Definición de modelo (estructura de tabla)
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
age: {
type: DataTypes.INTEGER
}
});
// Operaciones CRUD (¡Sin SQL, solo JavaScript!)
async function ormExample() {
// CREATE - Crear
const user = await User.create({
name: 'Juan',
email: 'juan@mail.com',
age: 25
});
console.log('Creado:', user.toJSON());
// READ - Consultar
const allUsers = await User.findAll();
console.log('Todos los usuarios:', allUsers);
// READ - Consulta condicional
const youngUsers = await User.findAll({
where: { age: { [Sequelize.Op.gte]: 20 } },
order: [['age', 'DESC']]
});
// READ - Consultar uno
const oneUser = await User.findOne({
where: { email: 'juan@mail.com' }
});
// UPDATE - Actualizar
await User.update(
{ age: 26 },
{ where: { name: 'Juan' } }
);
// DELETE - Eliminar
await User.destroy({
where: { id: 1 }
});
}
Configuración de Relaciones (JOIN)
// Configuración de relación entre usuario y pedidos
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: DataTypes.STRING
});
const Order = sequelize.define('Order', {
product: DataTypes.STRING,
price: DataTypes.DECIMAL(10, 2)
});
// Definición de relación: Un usuario puede tener múltiples pedidos
User.hasMany(Order);
Order.belongsTo(User);
// Consulta JOIN
async function getUserWithOrders(userId) {
const userWithOrders = await User.findOne({
where: { id: userId },
include: Order // JOIN
});
console.log(userWithOrders.toJSON());
// {
// id: 1,
// name: 'Juan',
// email: 'juan@mail.com',
// Orders: [
// { product: 'Portátil', price: 1500 },
// { product: 'Ratón', price: 30 }
// ]
// }
}
🤔 Preguntas Frecuentes
Q1. ¿Por qué usar bases de datos?
R: Muchas ventajas sobre sistemas de archivos:
❌ Sistema de Archivos (ej: users.txt)
├─ Posible duplicación de datos
├─ Problemas de acceso concurrente
├─ Copia/recuperación difícil
├─ Vulnerabilidades de seguridad
└─ Búsquedas lentas
✅ Base de Datos
├─ Integridad de datos garantizada
├─ Control de concurrencia (múltiples usuarios)
├─ Copia/recuperación automatizada
├─ Gestión de permisos de acceso
├─ Búsquedas rápidas (índices)
└─ Soporte de transacciones
Q2. ¿Qué base de datos elegir?
R: Depende de los requisitos del proyecto:
// Bases de Datos Relacionales (SQL)
MySQL / PostgreSQL / SQLite
├─ Pros: Estructura de datos precisa, transacciones
├─ Contras: Baja flexibilidad, escalabilidad limitada
└─ Adecuado: Finanzas, comercio electrónico, gestión de usuarios
// Bases de Datos No Relacionales (NoSQL)
MongoDB / Redis / Cassandra
├─ Pros: Esquema flexible, escalado horizontal
├─ Contras: Difícil manejo de relaciones complejas
└─ Adecuado: Redes sociales, análisis en tiempo real, caché
Q3. ¿Qué es un Índice (Index)?
R: Una estructura de datos que acelera la recuperación de datos:
-- Sin índice
SELECT * FROM users WHERE email = 'test@mail.com';
-- → Revisar 1M de filas (lento)
-- Crear índice
CREATE INDEX idx_email ON users(email);
-- Con índice
SELECT * FROM users WHERE email = 'test@mail.com';
-- → Buscar directamente vía índice (¡rápido!)
-- Desventaja: Escrituras más lentas (el índice debe actualizarse)
Analogía: Como el índice o tabla de contenidos de un libro, permite encontrar rápidamente lo que buscas.
Q4. ¿Qué es una Transacción (Transaction)?
R: Agrupar múltiples operaciones como una sola unidad:
// Ejemplo de transferencia bancaria
async function transferMoney(fromId, toId, amount) {
const connection = await pool.getConnection();
try {
// Iniciar transacción
await connection.beginTransaction();
// 1. Disminuir saldo del remitente
await connection.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
[amount, fromId]
);
// 2. Aumentar saldo del receptor
await connection.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
[amount, toId]
);
// Todo éxito → Confirmar
await connection.commit();
console.log('¡Transferencia completa!');
} catch (error) {
// Error → Revertir todo
await connection.rollback();
console.log('Transferencia fallida, revertida');
throw error;
} finally {
connection.release();
}
}
// Principios ACID
// Atomicity (Atomicidad): Todo o nada
// Consistency (Consistencia): Sin violación de reglas
// Isolation (Aislamiento): Independiente de otras transacciones
// Durability (Durabilidad): Almacenamiento permanente tras completar
Q5. ¿Qué es SQL Injection?
R: Un ataque que inyecta código SQL malicioso:
// ❌ Código peligroso (vulnerable a SQL Injection)
const email = req.body.email; // "admin@mail.com' OR '1'='1"
const query = `SELECT * FROM users WHERE email = '${email}'`;
// Ejecuta: SELECT * FROM users WHERE email = 'admin@mail.com' OR '1'='1'
// → ¡Fuga de información de todos los usuarios!
// ✅ Código seguro (Prepared Statement)
const [rows] = await pool.execute(
'SELECT * FROM users WHERE email = ?',
[email] // Automáticamente escapado
);
// Uso de ORM (defensa automática)
const user = await User.findOne({
where: { email: email } // Seguro
});
🎓 Próximos Pasos
Después de comprender bases de datos, aprende:
- SQL vs NoSQL - Guía de selección de base de datos
- ¿Qué es Node.js? - Desarrollo backend
- ¿Qué es una API? - Conexión entre base de datos y frontend
Práctica
# Instalación y ejecución de MySQL
brew install mysql # macOS
sudo apt install mysql # Linux
# Conexión a base de datos
mysql -u root -p
# Crear base de datos
CREATE DATABASE myapp;
USE myapp;
# Crear tabla y añadir datos
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES ('Juan', 'test@mail.com');
SELECT * FROM users;
🎬 Resumen
Las bases de datos son el núcleo de todas las aplicaciones:
- Base de Datos: Colección estructurada de datos
- CRUD: Crear, Leer, Actualizar, Eliminar - operaciones básicas
- Tabla: Organiza datos en filas y columnas
- Relación: Conexiones entre tablas (JOIN)
- Transacción: Procesamiento seguro de datos
¡Comprender bien las bases de datos permite construir aplicaciones estables y escalables! 💾✨