Aprende SQL · lección gratuita
Todo este curso corrió sobre SQLite compilado a WebAssembly, directo en tu navegador — perfecto para aprender sin instalar nada, pero una aplicación real no vive así. El SQL que escribiste vive dentro del código de un servidor (Node.js, Python, PHP...) que abre una conexión a una base de datos real y le envía esas mismas sentencias. La buena noticia: el SQL que aprendiste no cambia. Lo que cambia es cómo lo envías desde tu código.
node:sqlite: módulo nativo de Node.js (estable desde la v24 LTS) para hablar con un archivo .db — el mismo motor que usaste todo el curso, ahora en disco en vez de en el navegador.mysql2: driver de npm para conectarte a un servidor MySQL o MariaDB real, típico en producción.?). Es la misma regla de la lección de filtrado, ahora con consecuencias reales: sin ella, tu API queda abierta a inyección SQL.El código de este bloque es JavaScript real de Node.js — no se ejecuta aquí (no hay Node ni red dentro del navegador), es para que veas el patrón completo.
SQLite en disco, con node:sqlite:
import { DatabaseSync } from 'node:sqlite'
const db = new DatabaseSync('nexus.db')
// Consulta parametrizada: el '?' recibe el valor por separado del texto SQL
const stmt = db.prepare('SELECT id, nombre, precio FROM productos WHERE id = ?')
const producto = stmt.get(3) // una fila
console.log(producto)
const todos = db.prepare('SELECT * FROM productos WHERE stock > ?').all(50) // varias filas
MySQL/MariaDB en un servidor, con mysql2:
import mysql from 'mysql2/promise'
// El pool abre varias conexiones y las reparte entre requests —
// mucho más eficiente que abrir/cerrar una conexión por cada petición.
const pool = mysql.createPool({
host: 'localhost',
user: 'app_nexus',
password: process.env.DB_PASSWORD, // nunca la contraseña en el código
database: 'nexus',
})
async function obtenerProducto(id) {
const [filas] = await pool.query(
'SELECT id, nombre, precio FROM productos WHERE id = ?',
[id] // el valor viaja aparte, nunca concatenado
)
return filas[0]
}
Nota la diferencia clave con lo que hiciste todo el curso: aquí el resultado NO aparece solo en pantalla — vuelve como un objeto JavaScript (producto.precio, filas[0].nombre) que tu servidor usa para construir una respuesta, renderizar una página o alimentar otra lógica.
Estos SÍ son ejecutables — son el SQL exacto que un endpoint de Node.js enviaría, corriendo aquí contra el dataset Nexus para que veas el resultado real.
-- Endpoint: GET /api/productos/:id
-- En Node: db.prepare('SELECT id, nombre, precio, stock FROM productos WHERE id = ?').get(id)
SELECT id, nombre, precio, stock FROM productos WHERE id = 3;
-- Endpoint: GET /api/empleados?departamento=2
-- En Node: pool.query('SELECT nombre, cargo, salario FROM empleados WHERE departamento_id = ?', [depId
) SELECT nombre, cargo, salario FROM empleados WHERE departamento_id = 2 ORDER BY salario DESC;]
-- Endpoint: POST /api/productos (crear uno nuevo)
-- En Node: pool.query('INSERT INTO productos (nombre, categoria_id, precio, costo, stock) VALUES (?, ?, ?, ?, ?)', [...
) DROP TABLE IF EXISTS productos_demo; CREATE TABLE productos_demo AS SELECT FROM productos WHERE 0; INSERT INTO productos_demo (id, nombre, categoria_id, precio, costo, stock) VALUES (99, 'Backup Externo 2TB', 4, 1800, 700, 60); SELECT FROM productos_demo;]
⚠️ Si en vez deWHERE id = ?+[id]alguien concatenara el valor directo —WHERE id = ' + id + '—, mandarid = "3 OR 1=1"devolvería TODA la tabla. Esa es la inyección SQL de la que habla el <a href="/aprende-sql/glosario">Glosario</a>: no es teoría, es el motivo real por el que siempre se parametriza.
| Qué necesitas | node:sqlite (archivo local) | mysql2 (servidor real) |
|---|---|---|
| Conectar | new DatabaseSync('archivo.db') | mysql.createPool({...}) |
| Una fila | db.prepare(sql).get(valor) | (await pool.query(sql,[valor]))[0][0] |
| Varias filas | db.prepare(sql).all(valor) | (await pool.query(sql,[valor]))[0] |
| Parametrizar | ? en el SQL + argumento aparte | ? en el SQL + array de argumentos |
| Async | No (todo es síncrono) | Sí (siempre con await) |
| Instalación | Nativo, no instala nada | npm install mysql2 |
---
← Triggers y automatizaciónNoSQL: cuando el modelo relacional no es la respuesta →