Skip to content

¿Qué es PostgreSQL? ​

PostgreSQL lleva más de 35 años de desarrollo y hoy es la base de datos más querida por los desarrolladores según las encuestas de Stack Overflow. En esta lección conocerás su historia, sus características principales, en qué se diferencia de MySQL y cómo decidir cuál usar en cada proyecto.

Concepto ​

PostgreSQL es un SGBD objeto-relacional de código abierto. "Relacional" porque organiza los datos en tablas con SQL; "objeto" porque además permite definir tipos propios, herencia de tablas, funciones en varios lenguajes y extensiones que añaden capacidades nuevas.

Si MySQL es un coche confiable y económico que encuentras en cualquier taller, PostgreSQL es una camioneta todoterreno con caja de herramientas incluida: igual de confiable, con más capacidades y ligeramente más exigente de configurar.

Un poco de historia ​

AñoHito
1986Michael Stonebraker inicia POSTGRES en la Universidad de Berkeley (sucesor de Ingres)
1995Se añade soporte SQL: Postgres95
1996Cambia de nombre a PostgreSQL y pasa a ser un proyecto comunitario
2010Versión 9.0: replicación integrada
20149.4: tipo JSONB
201710: particionamiento declarativo, replicación lógica, IDENTITY
2020sUna versión mayor cada año (16, 17...), cada una con 5 años de soporte

PostgreSQL no tiene dueño: lo desarrolla una comunidad global con apoyo de muchas empresas, bajo una licencia muy permisiva (similar a MIT/BSD). Nadie puede "comprarlo" ni cambiarle la licencia.

Características principales ​

CaracterísticaQué significa para ti
Cumplimiento del estándar SQLLo que aprendiste en el curso de SQL funciona tal cual, incluidas CTEs, ventanas y FULL JOIN
ACID estrictoTransacciones confiables; hasta los cambios de estructura (CREATE, ALTER) son transaccionales
MVCCLas lecturas no bloquean escrituras y viceversa
Tipos avanzadosJSONB, arrays, UUID, rangos, INET, geometría, enums, tipos propios
Índices variadosB-tree, Hash, GIN, GiST, SP-GiST, BRIN; parciales y de expresión
Búsqueda de texto completoIntegrada, con soporte para español
ExtensionesPostGIS (mapas), pgvector (IA/embeddings), pg_trgm, TimescaleDB, pg_cron...
Lenguajes proceduralesPL/pgSQL, y también Python, JavaScript (plv8), Perl
SeguridadRoles granulares, Row Level Security (RLS), SSL

DDL transaccional: una joya poco conocida ​

sql
BEGIN;
ALTER TABLE productos ADD COLUMN descripcion TEXT;
CREATE INDEX idx_productos_nombre ON productos (nombre);
-- algo salió mal en la migración...
ROLLBACK;   -- ¡la columna y el índice desaparecen como si nada!

En MySQL, cada ALTER TABLE hace commit automático: si una migración falla a la mitad, la base queda en un estado intermedio. En PostgreSQL, toda la migración puede ser atómica.

PostgreSQL vs MySQL ​

AspectoPostgreSQLMySQL
LicenciaPostgreSQL License (muy permisiva), comunitarioGPL / comercial, propiedad de Oracle
Estándar SQLMuy apegadoMás permisivo, con extensiones propias
Comportamiento ante datos inválidosSiempre estricto (rechaza)Estricto solo si sql_mode lo indica
CHECKSiempreDesde 8.0.16
DDL transaccionalSíNo
JSONJSON y JSONB (binario, indexable con GIN)JSON (binario), índices vía columnas generadas
ArraysSíNo
EnumsCREATE TYPE ... AS ENUM reutilizableENUM por columna
UUID nativoSí (gen_random_uuid())Se guarda como CHAR(36) o BINARY(16)
FULL OUTER JOINSíNo (se emula)
Vistas materializadasSíNo
Índices parciales y de expresiónSíExpresión desde 8.0.13; parciales no
Texto completoPotente, con diccionarios por idiomaFULLTEXT más básico
Mayúsculas en LIKEDistingue (usa ILIKE)Normalmente no distingue
AutoincrementoIDENTITY / SERIALAUTO_INCREMENT
Hosting compartido (cPanel)Poco comúnCasi siempre
Servicios en la nubeSupabase, Neon, RDS, Cloud SQL, Railway, RenderPlanetScale, RDS, Cloud SQL
MantenimientoRequiere VACUUM (automático con autovacuum)Menos tareas visibles

Diferencias de sintaxis que te encontrarás ​

NecesidadPostgreSQLMySQL
Comillas para identificadores"columna"`columna`
Concatenar'a' || 'b' o CONCAT()CONCAT()
Búsqueda sin mayúsculasILIKELIKE
Id del último INSERTINSERT ... RETURNING idLAST_INSERT_ID()
Fecha actual con horanow()NOW()
Conversión de tipos'2024-01-01'::date o CAST(...)CAST(...)
Limitar filasLIMIT 10 OFFSET 20LIMIT 20, 10 o LIMIT 10 OFFSET 20
"Insertar o actualizar"INSERT ... ON CONFLICT (col) DO UPDATEINSERT ... ON DUPLICATE KEY UPDATE
BooleanosTRUE/FALSE reales1/0
sql
-- "Upsert" en PostgreSQL: inserta o actualiza el stock si el SKU ya existe
INSERT INTO productos (sku, nombre, precio, stock)
VALUES ('ELE-001', 'Audífonos Bluetooth', 899.00, 30)
ON CONFLICT (sku)
DO UPDATE SET stock = EXCLUDED.stock, precio = EXCLUDED.precio;

Error común: nombres con mayúsculas

PostgreSQL convierte a minúsculas los identificadores sin comillas: CREATE TABLE Clientes crea clientes. Pero si usas comillas ("Clientes"), el nombre queda con mayúscula y siempre tendrás que escribirlo con comillas. Algunas herramientas (y Prisma por defecto con modelos en PascalCase) generan nombres así. Usa nombres en minúsculas con guion bajo (detalle_pedido) y te ahorrarás problemas.

¿Cuándo elegir cada uno? ​

Elige PostgreSQL si...Elige MySQL si...
Usas Supabase, Neon, Django, Rails o PrismaEl proyecto vivirá en hosting compartido con cPanel
Necesitas JSONB, arrays, búsqueda de texto o geodatosUsas WordPress, WooCommerce, PrestaShop, Moodle
Quieres reglas estrictas y migraciones atómicasEl equipo o cliente ya tiene experiencia y herramientas MySQL
Haces reportes o analítica con SQL complejoNecesitas la opción más barata y disponible
Planeas IA con embeddings (pgvector)Es un proyecto Laravel tradicional en hosting

Recomendación práctica

Para proyectos nuevos con Node.js, Next.js o servicios modernos en la nube, PostgreSQL es una apuesta excelente. Para sitios de clientes en hosting compartido y el ecosistema WordPress, MySQL. Saber ambos te hace mucho más contratable.

Ejemplo: un vistazo a lo que hace especial a Postgres ​

sql
-- Tabla de productos con tipos que MySQL no tiene (o no igual)
CREATE TABLE productos (
  id          INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  uuid        UUID NOT NULL DEFAULT gen_random_uuid() UNIQUE,
  nombre      TEXT NOT NULL,
  precio      NUMERIC(10,2) NOT NULL CHECK (precio >= 0),
  etiquetas   TEXT[] NOT NULL DEFAULT '{}',          -- array de textos
  atributos   JSONB NOT NULL DEFAULT '{}',           -- documento JSON binario
  creado_en   TIMESTAMPTZ NOT NULL DEFAULT now()     -- fecha con zona horaria
);

INSERT INTO productos (nombre, precio, etiquetas, atributos) VALUES
  ('Audífonos Bluetooth', 899.00, ARRAY['audio', 'inalámbrico'],
   '{"color": "negro", "bateria_horas": 30}'),
  ('Teclado mecánico', 1250.00, ARRAY['gamer', 'oficina'],
   '{"switches": "red", "idioma": "es", "rgb": true}')
RETURNING id, uuid, nombre;

-- Productos con la etiqueta 'gamer'
SELECT nombre FROM productos WHERE 'gamer' = ANY (etiquetas);

-- Productos con RGB (consulta dentro del JSON)
SELECT nombre, atributos ->> 'switches' AS switches
FROM productos
WHERE atributos @> '{"rgb": true}';
nombreswitches
Teclado mecánicored

Verás todo esto a detalle en Tipos avanzados.

Ejercicios ​

  1. Menciona tres características de PostgreSQL que MySQL no tiene (o tiene de forma limitada).
  2. ¿Qué significa que el DDL sea transaccional y por qué ayuda en las migraciones?
  3. Un cliente quiere una tienda con WooCommerce en su hosting de cPanel. ¿Qué base de datos usarías? ¿Y para una app con Next.js y Supabase?
  4. Reescribe para PostgreSQL esta consulta de MySQL: SELECT `nombre` FROM `clientes` WHERE nombre LIKE '%ana%'; (sin importar mayúsculas).
Ver solución
  1. Por ejemplo: arrays, JSONB indexable con GIN, vistas materializadas, índices parciales, FULL OUTER JOIN, DDL transaccional, UUID nativo, RLS.
  2. Que los cambios de estructura (CREATE, ALTER, DROP) participan en transacciones: si una migración de varios pasos falla, un ROLLBACK deja la base exactamente como estaba, sin estados intermedios.
  3. WooCommerce en cPanel: MySQL/MariaDB (WordPress lo requiere y es lo que ofrece el hosting). Next.js + Supabase: PostgreSQL (Supabase es PostgreSQL).
sql
SELECT nombre FROM clientes WHERE nombre ILIKE '%ana%';

Resumen ​

  • PostgreSQL es un SGBD objeto-relacional, comunitario y de licencia permisiva, con más de 35 años de historia.
  • Destaca por su apego al estándar, ACID estricto, DDL transaccional, tipos avanzados y extensiones.
  • Frente a MySQL: más estricto y con más funciones; MySQL gana en disponibilidad en hosting compartido.
  • Cuidado con las diferencias de sintaxis: comillas dobles, ILIKE, RETURNING, ON CONFLICT.
  • Usa nombres en minúsculas para evitar el problema de las comillas.

Academia Web — aprende, copia y construye.