Aprende SQL · lección gratuita

Lección 45 · SQL en producción: conectar con Node.js

Resumen

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.

Sintaxis / Conceptos

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.

Ejemplos

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 de WHERE id = ? + [id] alguien concatenara el valor directo — WHERE id = ' + id + ' —, mandar id = "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.

Cheatsheet

Qué necesitasnode:sqlite (archivo local)mysql2 (servidor real)
Conectarnew DatabaseSync('archivo.db')mysql.createPool({...})
Una filadb.prepare(sql).get(valor)(await pool.query(sql,[valor]))[0][0]
Varias filasdb.prepare(sql).all(valor)(await pool.query(sql,[valor]))[0]
Parametrizar? en el SQL + argumento aparte? en el SQL + array de argumentos
AsyncNo (todo es síncrono)Sí (siempre con await)
InstalaciónNativo, no instala nadanpm install mysql2

---

← Triggers y automatizaciónNoSQL: cuando el modelo relacional no es la respuesta →

Ver todas las lecciones de Aprende SQL →