Introducción a PostgreSQL: instalación, psql y primeras consultas

PostgreSQL empezó como un proyecto de investigación en la Universidad de California en Berkeley a mediados de los años ochenta, y desde entonces se ha convertido en una de las bases de datos relacionales de código abierto más usadas del mundo. Su comunidad publica una versión mayor cada año y mantiene cada una con correcciones durante cinco años, lo que la hace una opción estable tanto para proyectos personales como para sistemas de empresas grandes.

Esta guía está organizada por etapas: instalar, conectarte, crear tu primera base de datos con tablas bien definidas, hacer consultas y sacar una copia de seguridad. Si ya conoces SQL en general, aquí vas a encontrar lo que es propio de PostgreSQL: sus tipos de datos, la consola psql, RETURNING, ILIKE y el famoso "upsert" con ON CONFLICT.
Etapa 1: instalación
Elige el método según tu sistema. Todos instalan el servidor y el cliente de línea de comandos psql.
Windows
Descarga el instalador desde la sección de descargas del sitio oficial (postgresql.org), que enlaza al paquete preparado por EDB. Durante la instalación te pedirá tres datos que debes anotar:
- La contraseña del superusuario
postgres. Sin ella no podrás entrar después. - El puerto, que por defecto es 5432. Déjalo así salvo que ya tengas otro servicio usándolo.
- Los componentes. Marca al menos el servidor, las herramientas de línea de comandos y pgAdmin, que es la interfaz gráfica oficial.
Al terminar, abre "SQL Shell (psql)" desde el menú Inicio. Acepta los valores por defecto con Enter y escribe la contraseña que definiste.
macOS
Las dos opciones más cómodas son Postgres.app, una aplicación que se arrastra a la carpeta Aplicaciones y se inicia con un clic, o Homebrew. Con Homebrew se instala una versión concreta, por ejemplo:
brew install postgresql@17
brew services start postgresql@17Linux (Debian y Ubuntu)
sudo apt update
sudo apt install postgresql
sudo -u postgres psqlEn Linux, el instalador crea un usuario del sistema llamado postgres y configura la autenticación para que ese usuario entre sin contraseña. Por eso el tercer comando funciona: ejecutas psql como ese usuario.
Con Docker
Si prefieres no instalar nada en tu sistema, un contenedor es suficiente para aprender:
docker run --name pg -e POSTGRES_PASSWORD=secreto -p 5432:5432 -d postgres:17
docker exec -it pg psql -U postgresEtapa 2: moverte por psql
psql acepta dos tipos de entrada: sentencias SQL, que terminan con punto y coma, y metacomandos, que empiezan con barra invertida y no llevan punto y coma. Estos son los que vas a usar todo el tiempo:
| Metacomando | Qué hace |
|---|---|
\l | Lista las bases de datos |
\c tienda | Se conecta a la base tienda |
\dt | Lista las tablas de la base actual |
\d clientes | Muestra columnas, tipos, índices y restricciones de una tabla |
\du | Lista los roles (usuarios) |
\x | Alterna la vista expandida, útil para filas con muchas columnas |
\h CREATE TABLE | Ayuda de sintaxis de una sentencia SQL |
\? | Ayuda de todos los metacomandos |
\q | Sale de psql |
Si escribes una sentencia y olvidas el punto y coma, el indicador cambia de =# a -#. No es un error: psql está esperando que termines. Escribe ; y Enter.
Etapa 3: crear un usuario y una base de datos
Trabajar siempre con el superusuario postgres es mala idea, igual que usar la cuenta de administrador para todo en tu sistema operativo. Crea un rol propio para tu aplicación:
CREATE ROLE tienda_app WITH LOGIN PASSWORD 'una-clave-larga-y-unica';
CREATE DATABASE tienda OWNER tienda_app;Sal con \q y vuelve a entrar con ese usuario:
psql -U tienda_app -d tienda -h localhostLa opción -h localhost fuerza una conexión por red local, que usa autenticación por contraseña. En Linux, si la omites, psql intenta conectarse por un socket local y puede fallar con un error de autenticación "peer", porque tu usuario del sistema no se llama tienda_app.
Etapa 4: tablas con tipos bien elegidos
PostgreSQL tiene una lista de tipos de datos más rica que la de muchos motores. Elegir bien desde el inicio evita conversiones y errores más adelante.
| Tipo | Úsalo para | Nota |
|---|---|---|
integer / bigint | Números enteros, identificadores | bigint si esperas más de unos 2.100 millones de filas |
numeric(10,2) | Dinero y cantidades exactas | Nunca uses real o double precision para dinero |
text | Texto de cualquier longitud | En PostgreSQL no es más lento que varchar |
boolean | Verdadero o falso | Acepta true, false y algunos sinónimos |
date | Fechas sin hora | Formato ISO: 2025-06-30 |
timestamptz | Momentos exactos en el tiempo | Guarda en UTC y convierte según la zona de la sesión |
jsonb | Datos semiestructurados | Permite consultar e indexar campos internos |
Con eso, creemos dos tablas relacionadas:
CREATE TABLE clientes (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
nombre text NOT NULL,
email text NOT NULL UNIQUE,
creado_en timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE pedidos (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
cliente_id integer NOT NULL REFERENCES clientes(id) ON DELETE CASCADE,
total numeric(10,2) NOT NULL CHECK (total >= 0),
estado text NOT NULL DEFAULT 'pendiente',
detalles jsonb,
creado_en timestamptz NOT NULL DEFAULT now()
);Algunos detalles que vale la pena entender:
GENERATED ALWAYS AS IDENTITYes la forma estándar de crear claves autoincrementales. Verás muchoserialen tutoriales antiguos; sigue funcionando, pero la identidad es la opción recomendada hoy.REFERENCES clientes(id)crea una clave foránea: no podrás insertar un pedido con un cliente que no existe.ON DELETE CASCADEborra los pedidos cuando se borra el cliente. Piénsalo bien antes de usarlo; en muchos sistemas es preferible impedir el borrado.CHECK (total >= 0)rechaza totales negativos directamente en la base, sin depender de que la aplicación valide.
Comprueba el resultado con \d pedidos.
Etapa 5: insertar, consultar y modificar
Insertar y recuperar lo insertado
RETURNING devuelve las filas afectadas, así no necesitas una segunda consulta para saber qué identificador se generó:
INSERT INTO clientes (nombre, email) VALUES
('Laura Gómez', 'laura@example.com'),
('Andrés Ruiz', 'andres@example.com')
RETURNING id, nombre;
INSERT INTO pedidos (cliente_id, total, detalles) VALUES
(1, 125000.00, '{"productos": ["teclado", "mouse"], "envio": "express"}'),
(1, 48000.50, '{"productos": ["cable USB-C"]}'),
(2, 310000.00, '{"productos": ["monitor"], "envio": "normal"}');Consultas propias de PostgreSQL
ILIKE busca sin distinguir mayúsculas de minúsculas:
SELECT nombre, email FROM clientes WHERE nombre ILIKE '%gómez%';El operador ->> extrae un campo de un jsonb como texto:
SELECT id, total, detalles->>'envio' AS envio
FROM pedidos
WHERE detalles->>'envio' = 'express';Y una consulta con unión y agregación, para ver cuánto ha comprado cada cliente:
SELECT c.nombre, count(p.id) AS pedidos, coalesce(sum(p.total), 0) AS total_comprado
FROM clientes c
LEFT JOIN pedidos p ON p.cliente_id = c.id
GROUP BY c.nombre
ORDER BY total_comprado DESC;Insertar o actualizar en una sola sentencia
Cuando importas datos que pueden existir ya, ON CONFLICT evita errores de duplicado:
INSERT INTO clientes (nombre, email)
VALUES ('Laura G. Gómez', 'laura@example.com')
ON CONFLICT (email) DO UPDATE SET nombre = EXCLUDED.nombre;EXCLUDED representa la fila que intentaste insertar. Para que funcione, la columna del conflicto debe tener una restricción UNIQUE o ser clave primaria.
Modificar con red de seguridad
En psql, cada sentencia se confirma automáticamente. Para cambios delicados, abre una transacción: puedes revisar el efecto y deshacerlo si algo salió mal.
BEGIN;
UPDATE pedidos SET estado = 'enviado' WHERE id = 1;
SELECT id, estado FROM pedidos;
-- Si todo está bien:
COMMIT;
-- Si no, en lugar de COMMIT:
-- ROLLBACK;Etapa 6: copias de seguridad
pg_dump genera una copia de una base de datos sin detener el servidor. El formato personalizado (-F c) está comprimido y permite restaurar tablas sueltas:
pg_dump -U tienda_app -h localhost -d tienda -F c -f tienda.dump
pg_restore -U tienda_app -h localhost -d tienda_copia tienda.dumpLa base de destino (tienda_copia en el ejemplo) debe existir antes de restaurar. Guarda las copias fuera del servidor y, cada cierto tiempo, prueba restaurarlas: una copia que nunca se ha restaurado es una suposición, no un respaldo.
Errores que vas a encontrar en la primera semana
"password authentication failed for user". La contraseña es incorrecta o el usuario no existe. Verifica con \du desde una sesión de superusuario.
"Peer authentication failed". Te conectaste en Linux sin -h localhost con un usuario que no coincide con tu usuario del sistema. Agrega -h localhost.
"relation does not exist". La tabla no existe en la base a la que estás conectado, o escribiste el nombre con mayúsculas al crearla usando comillas dobles. PostgreSQL convierte a minúsculas los nombres sin comillas; si creaste "Clientes" con comillas, tendrás que escribirlo siempre así. Por eso conviene usar nombres en minúsculas y sin comillas.
"could not connect to server". El servicio no está iniciado o escucha en otro puerto. En Linux revisa con sudo systemctl status postgresql.
Hacia dónde seguir
Con tablas, restricciones, consultas y copias de seguridad ya tienes una base sólida. El siguiente tema natural es el rendimiento: cuando una tabla pasa de cientos a cientos de miles de filas, las consultas que antes eran instantáneas empiezan a tardar. Ahí entran los índices y el comando EXPLAIN, que muestra cómo planea PostgreSQL ejecutar cada consulta. Mientras tanto, practica creando una tabla productos y relacionándola con pedidos mediante una tabla intermedia: es el ejercicio que más enseña sobre diseño relacional.
Si quieres conocer otros artículos parecidos a Introducción a PostgreSQL: instalación, psql y primeras consultas puedes visitar la categoría Guias y Tutoriales.
Deja una respuesta

Contenido que te pude interesar