Capítulo 1 de 15 11 secciones 11 min

Qué es SQL y por qué hay cuatro

MySQL, SQL Server, PostgreSQL y SQLite: qué comparten, qué no, y cuál te va a tocar en el trabajo.

SQL es el lenguaje para pedirle datos a una base de datos, y es uno solo en lo esencial: el SELECT, el WHERE, el GROUP BY y los JOIN se escriben igual en PostgreSQL, MySQL, SQL Server y SQLite. Lo que cambia es alrededor del 20%: cómo se limitan filas, cómo se juntan textos, las funciones de fecha y los tipos de dato. Ese 20% es justo el que aparece el primer día de trabajo.

Hola! Empecemos por la confusión más común

Vas a buscar "cómo aprender SQL" y en dos minutos aparecen cuatro nombres: MySQL, SQL Server, PostgreSQL y SQLite. Y la pregunta obvia: ¿cuál aprendo? 😅

Te doy la respuesta de una y después la explico: aprendes SQL, no un motor. El 80% de lo que vas a escribir en tu vida es idéntico en los cuatro. Lo que cambia es un 20% que se puede tener en una tabla al lado, y en este libro lo vas a tener en cada capítulo 💜

Qué es SQL, sin rodeos

SQL es el lenguaje para pedirle datos a una base de datos. Se lee casi como una frase en inglés:

SELECT nombre, ciudad
FROM clientes
WHERE ciudad = 'Lima';

"Selecciona el nombre y la ciudad, de la tabla clientes, donde la ciudad sea Lima". Ya está, eso es SQL.

Y aquí está lo que lo hace especial: tú dices QUÉ quieres, no CÓMO buscarlo. No le explicas que recorra las filas ni por dónde empezar. El motor decide eso solo, y suele decidirlo mejor que tú.

Por eso SQL lleva cincuenta años en pie mientras aparecen y desaparecen lenguajes: lo que se pide no cambia aunque cambie la forma de guardarlo.

Motor, base de datos y SQL, que no son lo mismo

Esta confusión la tiene todo el mundo al empezar, así que la aclaro con una imagen que a mí me sirvió.

  • 📖 SQL es el idioma.
  • ⚙️ El motor (PostgreSQL, MySQL, SQL Server, SQLite) es el programa que lo entiende y guarda los datos. Se le dice también gestor o DBMS.
  • 🗃️ La base de datos es tu conjunto de tablas concreto: la de ventas de tu empresa.

Es como decir que el español es el idioma, la persona que lo habla es el motor, y lo que te está contando es la base. Cuatro personas pueden hablar español con acentos distintos y entenderse perfecto 🌸

Los cuatro, y dónde te los vas a encontrar

MotorDónde apareceQué conviene saber
PostgreSQLStartups, fintech, analítica, casi todo lo nuevoEl más completo y el más estricto. Si aprendes aquí, el resto te resulta fácil
MySQLWeb, ecommerce, WordPress, sistemas heredadosEl más extendido del mundo. MariaDB es su gemelo y va casi igual
SQL ServerEmpresas grandes, banca, retail, todo lo MicrosoftSu dialecto se llama T-SQL y es el que más se aparta. Muy común en Perú
SQLiteCelulares, apps de escritorio, un archivo sueltoNo tiene servidor: la base es un archivo. Es con el que vamos a practicar

Si trabajas en una empresa grande peruana, lo más probable es SQL Server. Si es una startup o algo montado en los últimos años, PostgreSQL. Si es una tienda online o algo con WordPress detrás, MySQL 📊

Y hay un quinto grupo que conviene nombrar: los de la nube, como BigQuery de Google, Snowflake o Redshift de Amazon. Son otra cosa por dentro, pero el SQL que escribes ahí se parece muchísimo al de PostgreSQL, así que lo de este libro te sirve igual.

Qué es igual en los cuatro

Esto es lo que quiero que te lleves del capítulo, porque quita el miedo: casi todo.

Existe un estándar, el ANSI SQL, que los cuatro respetan en lo fundamental. Lo que se escribe igual en todos:

  • SELECT, FROM, WHERE
  • GROUP BY y HAVING
  • ✅ Los cuatro JOIN
  • ORDER BY
  • COUNT, SUM, AVG, MIN, MAX
  • INSERT, UPDATE, DELETE
  • ✅ Las subconsultas, los CTE con WITH y las funciones de ventana

O sea: los capítulos 3 al 9 de este libro, que son el corazón, valen tal cual en los cuatro motores 🌟

Y qué cambia

El 20% restante. Te lo adelanto entero aquí para que lo veas junto una vez, y después cada capítulo lo retoma en su momento.

Traer solo las primeras 10 filas

PostgreSQLSELECT * FROM clientes LIMIT 10;
MySQLSELECT * FROM clientes LIMIT 10;
SQL ServerSELECT TOP 10 * FROM clientes;
SQLiteSELECT * FROM clientes LIMIT 10;

Tres usan LIMIT y SQL Server usa TOP, que además va antes de las columnas. Es la primera diferencia con la que se choca todo el mundo.

Juntar dos textos

PostgreSQLSELECT nombre || ' - ' || ciudad FROM clientes;
MySQLSELECT CONCAT(nombre, ' - ', ciudad) FROM clientes;
SQL ServerSELECT nombre + ' - ' + ciudad FROM clientes;
SQLiteSELECT nombre || ' - ' || ciudad FROM clientes;

Tres formas distintas para lo mismo. El CONCAT de MySQL también funciona en PostgreSQL y en SQL Server, así que si quieres escribir algo que corra en los tres, usa CONCAT.

La fecha y hora de ahora

PostgreSQLSELECT NOW();
MySQLSELECT NOW();
SQL ServerSELECT GETDATE();
SQLiteSELECT datetime('now');

Y ojo: CURRENT_TIMESTAMP funciona en los cuatro. Cuando exista una forma estándar, esa es la que conviene usar.

Si viene nulo, ponme otro valor

PostgreSQLSELECT COALESCE(monto, 0) FROM pedidos;
MySQLSELECT IFNULL(monto, 0) FROM pedidos;
SQL ServerSELECT ISNULL(monto, 0) FROM pedidos;
SQLiteSELECT IFNULL(monto, 0) FROM pedidos;

COALESCE funciona en los cuatro y además acepta varios valores de repuesto. Es la que yo uso siempre.

¿Ves el patrón? Casi siempre hay una forma que funciona en los cuatro, y las diferencias están en los atajos que cada motor inventó por su cuenta. Si te acostumbras a la forma estándar, tu SQL viaja 💜

Las otras diferencias que vas a encontrar, y que veremos cada una en su capítulo:

  • 🔤 Las comillas. El texto va entre comillas simples en los cuatro. Los nombres de tabla y columna con espacios van entre comillas dobles en PostgreSQL y SQLite, entre acentos graves en MySQL y entre corchetes en SQL Server.
  • 🔢 Los tipos de dato. Capítulo 5.
  • 🆔 El id que se autoincrementa. Capítulo 11, y ahí los cuatro se escriben distinto.
  • 📅 Las funciones de fecha. Capítulo 6, y es donde más se pelean.
  • 🔠 Las mayúsculas. En MySQL sobre Windows, 'lima' y 'Lima' suelen ser lo mismo. En PostgreSQL no. Esa te puede cambiar un conteo sin que te enteres.

Con cuál practicamos, y por qué

Con SQLite, y no porque sea el más fácil sino por tres cosas muy concretas:

  • 💾 No hay que instalar un servidor. La base entera es un archivo. Lo descargas y ya.
  • 🐍 Python lo trae de fábrica. Cero configuración.
  • 📱 Lo usas todos los días sin saberlo. Tu celular tiene decenas de bases SQLite dentro: WhatsApp, el navegador, la galería.

Y lo importante: lo que aprendas aquí se escribe igual en los otros tres, salvo lo que este libro te va marcando en su tabla.

Cuando quieras probar los demás, sin instalar nada:

  • 🐘 DB Fiddle para PostgreSQL y MySQL en el navegador.
  • 🪟 dbfiddle.uk, que además tiene SQL Server.
Tres tablas enganchadas: clientes con la clave primaria id_cliente, pedidos que la repite como clave foránea y añade la suya, y detalle que a su vez apunta a pedidos. Un cliente tiene muchos pedidos y un pedido muchas líneas.
La clave foránea es todo el modelo relacional: la tabla de pedidos no guarda el nombre del cliente, guarda su id. Ese enganche es justo lo que un JOIN recorre, y por eso vale la pena entenderlo antes de llegar a los JOINs y no durante.

La base de este libro

Todo corre sobre tienda.db, una distribuidora con cinco tablas y relaciones de verdad. Vamos a mirarla:

SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;
name
-----------
clientes
detalle
direcciones
pedidos
productos

Esa consulta es de SQLite y no funciona igual en los otros. Es un buen ejemplo de algo que parece SQL normal y es específico del motor:

Listar las tablas que hay

PostgreSQL\dt (o consultar information_schema.tables)
MySQLSHOW TABLES;
SQL ServerSELECT name FROM sys.tables;
SQLiteSELECT name FROM sqlite_master WHERE type = 'table';

Los cuatro guardan su catálogo en un sitio distinto. PostgreSQL, MySQL y SQL Server sí tienen information_schema.tables, que es lo estándar y lo que conviene usar si quieres una sola consulta para los tres.

Y cuántas filas tiene cada una:

SELECT 'clientes' AS tabla, COUNT(*) AS filas FROM clientes
UNION ALL SELECT 'direcciones', COUNT(*) FROM direcciones
UNION ALL SELECT 'productos', COUNT(*) FROM productos
UNION ALL SELECT 'pedidos', COUNT(*) FROM pedidos
UNION ALL SELECT 'detalle', COUNT(*) FROM detalle;
tabla        filas
-----------  -----
clientes     120
direcciones  164
productos    40
pedidos      900
detalle      2682

Esa sí es SQL estándar y corre igual en los cuatro motores 🌟

Fíjate en la forma de las tablas, que dice mucho: 120 clientes hicieron 900 pedidos, y esos 900 pedidos tienen 2.682 líneas de detalle. O sea que cada cliente compró varias veces y cada compra tenía varios productos. Eso es una base relacional de verdad y por eso los JOIN del capítulo 7 van a tener sentido.

Tu primera consulta

SELECT nombre, ciudad, segmento
FROM clientes
WHERE ciudad = 'Lima'
ORDER BY nombre
LIMIT 5;
nombre                  ciudad  segmento
----------------------  ------  ----------
Almacenes Vega 010      Lima    Minimarket
Almacenes Vega 039      Lima    Mayorista
Almacenes Vega 072      Lima    Horeca
Autoservicio Norte 091  Lima    Bodega
Bodega La Esquina 005   Lima    Mayorista

Eso ya es una consulta completa: qué columnas quieres, de dónde, con qué filtro, en qué orden y cuántas 💜

Y salvo el LIMIT, esa consulta corre tal cual en los cuatro motores. En SQL Server sería SELECT TOP 5 nombre, ciudad, segmento y el resto igual.

Ejercicios

1. Cuántos clientes hay

Cuenta cuántos clientes tiene la tabla.

SELECT COUNT(*) AS clientes FROM clientes;
clientes
--------
120

COUNT(*) es estándar y funciona igual en los cuatro motores.

2. Las ciudades sin repetir

Lista las ciudades distintas que hay, ordenadas.

SELECT DISTINCT ciudad FROM clientes ORDER BY ciudad;
ciudad
--------
Arequipa
Chiclayo
Cusco
Lima
Piura
Trujillo
3. Los cinco productos más caros

Trae nombre y precio de los cinco productos con el precio más alto.

SELECT nombre, precio
FROM productos
ORDER BY precio DESC
LIMIT 5;
nombre       precio
-----------  ------
Producto 27  89.35
Producto 37  86.1
Producto 16  83.42
Producto 36  82.97
Producto 12  81.85

En SQL Server esto sería SELECT TOP 5 nombre, precio FROM productos ORDER BY precio DESC;. Todo lo demás igual.

4. Escríbelo para los cuatro motores

Sin ejecutar nada: escribe "los 3 pedidos más caros" en los cuatro dialectos.

-- PostgreSQL, MySQL y SQLite
SELECT id, monto FROM pedidos ORDER BY monto DESC LIMIT 3;

-- SQL Server
SELECT TOP 3 id, monto FROM pedidos ORDER BY monto DESC;

-- Y el estándar ANSI, que funciona en PostgreSQL y en SQL Server modernos
SELECT id, monto FROM pedidos ORDER BY monto DESC
FETCH FIRST 3 ROWS ONLY;

Esa tercera forma, FETCH FIRST, es la del estándar. Es más larga y casi nadie la usa, pero saber que existe te salva el día que veas una consulta escrita así y no entiendas de dónde salió 🙂

5. El filtro con texto

Trae los clientes del segmento Mayorista que sean de Arequipa.

SELECT nombre, ciudad, segmento
FROM clientes
WHERE segmento = 'Mayorista' AND ciudad = 'Arequipa';
nombre                 ciudad    segmento
---------------------  --------  ---------
Cafe del Puerto 060    Arequipa  Mayorista
Bodega San Martin 103  Arequipa  Mayorista
Minimarket El Sol 109  Arequipa  Mayorista

Las comillas simples para el texto son estándar. Si usas comillas dobles, PostgreSQL va a creer que le hablas de una columna llamada Mayorista y te va a dar un error raro.

6. La consulta que falla

Pide una columna que no existe y lee el error.

SELECT nombre, telefono FROM clientes LIMIT 3;
OperationalError: no such column: telefono

Los cuatro motores dicen lo mismo con otras palabras: PostgreSQL dice column "telefono" does not exist, MySQL Unknown column 'telefono' y SQL Server Invalid column name 'telefono'. Distinto texto, mismo problema 🙃

Lo que te llevas

  • 🗣️ SQL es el idioma; el motor es quien lo habla. Aprendes el idioma.
  • 🤝 El 80% se escribe igual en PostgreSQL, MySQL, SQL Server y SQLite.
  • ⚠️ El 20% que cambia aparece el primer día: limitar filas, juntar textos, fechas y nulos.
  • 🧭 Cuando exista una forma estándar (COALESCE, CONCAT, CURRENT_TIMESTAMP), esa es la que conviene.
  • 💾 Practicamos con SQLite porque es un archivo, y lo aprendido viaja.

En el capítulo 2 instalamos lo que haga falta y conectamos con la base, que es donde se atasca la gente antes de escribir su primer SELECT.

Que tengas un hermoso día! 🌟

¿Tienes alguna duda o consulta?