Résumé PostgreSQL : Référence rapide pour les développeurs
Référence rapide pour PostgreSQL
- Une référence rapide pour le travail quotidien
- PostgreSQL
- connexions, syntaxe SQL, méta-commandes psql, performance, JSON, fonctions analytiques et plus encore.
Si vous souhaitez un rappel concis couvrant plusieurs bases de données avant de plonger dans les spécificités de Postgres, ce barème SQL contenant les commandes SQL les plus utiles est un compagnon pratique.

Connexion et bases
# Connexion
psql -h HÔTE -p 5432 -U UTILISATEUR -d SDB
psql $DATABASE_URL
# À l'intérieur de psql
\conninfo -- afficher la connexion
\l[+] -- lister les bases de données
\c SDB -- se connecter à SDB
\dt[+] [schéma.]motif -- lister les tables
\dv[+] -- lister les vues
\ds[+] -- lister les séquences
\df[+] [motif] -- lister les fonctions
\d[S+] nom -- décrire table/vue/séquence
\dn[+] -- lister les schémas
\du[+] -- lister les rôles
\timing -- basculer le minutage des requêtes
\x -- affichage étendu
\e -- éditer le tampon dans $EDITOR
\i fichier.sql -- exécuter le fichier
\copy ... -- COPY côté client
\! commande_shell -- exécuter une commande shell
Types de données (courants)
- Numériques :
smallint,integer,bigint,decimal(p,s),numeric,real,double precision,serial,bigserial - Texte :
text,varchar(n),char(n) - Booléen :
boolean - Temporel :
timestamp [with/without time zone],date,time,interval - UUID :
uuid - JSON :
json,jsonb(recommandé) - Tableau :
type[]par exempletext[] - Réseau :
inet,cidr,macaddr - Géométrique :
point,line,polygon, etc.
Vérifier la version PostgreSQL
SELECT version();
Version du serveur PostgreSQL :
pg_config --version
Version du client PostgreSQL :
psql --version
DDL (Créer / Modifier)
-- Créer schéma et table
CREATE SCHEMA IF NOT EXISTS app;
CREATE TABLE app.users (
id bigserial PRIMARY KEY,
email text NOT NULL UNIQUE,
name text,
active boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT now(),
profile jsonb,
tags text[]
);
-- Modifier
ALTER TABLE app.users ADD COLUMN last_login timestamptz;
ALTER TABLE app.users ALTER COLUMN name SET NOT NULL;
ALTER TABLE app.users DROP COLUMN tags;
-- Contraintes
ALTER TABLE app.users ADD CONSTRAINT email_lower_uk UNIQUE (lower(email));
-- Index
CREATE INDEX ON app.users (email);
CREATE UNIQUE INDEX CONCURRENTLY users_email_uidx ON app.users (lower(email));
CREATE INDEX users_profile_gin ON app.users USING gin (profile);
CREATE INDEX users_created_at_idx ON app.users (created_at DESC);
DML (Insérer / Mettre à jour / Upsert / Supprimer)
INSERT INTO app.users (email, name) VALUES
('a@x.com','A'), ('b@x.com','B')
RETURNING id;
-- Upsert (ON CONFLICT)
INSERT INTO app.users (email, name)
VALUES ('a@x.com','Alice')
ON CONFLICT (email)
DO UPDATE SET name = EXCLUDED.name, updated_at = now();
UPDATE app.users SET active = false WHERE last_login < now() - interval '1 year';
DELETE FROM app.users WHERE active = false AND last_login IS NULL;
Essentiels de requêtage
SELECT * FROM app.users ORDER BY created_at DESC LIMIT 20 OFFSET 40; -- pagination
-- Filtrage
SELECT * FROM app.users WHERE email ILIKE '%@example.%' AND active;
-- Agrégats et GROUP BY
SELECT active, count(*) AS n
FROM app.users
GROUP BY active
HAVING count(*) > 10;
-- Jointures
SELECT o.id, u.email, o.total
FROM app.orders o
JOIN app.users u ON u.id = o.user_id
LEFT JOIN app.discounts d ON d.id = o.discount_id;
-- DISTINCT ON (spécifique à Postgres)
SELECT DISTINCT ON (user_id) user_id, status, created_at
FROM app.events
ORDER BY user_id, created_at DESC;
-- CTE (Common Table Expressions)
WITH recent AS (
SELECT * FROM app.orders WHERE created_at > now() - interval '30 days'
)
SELECT count(*) FROM recent;
-- CTE récursive
WITH RECURSIVE t(n) AS (
SELECT 1
UNION ALL
SELECT n+1 FROM t WHERE n < 10
)
SELECT sum(n) FROM t;
Fonctions analytiques (Window Functions)
SELECT
user_id,
created_at,
sum(total) OVER (PARTITION BY user_id ORDER BY created_at) AS running_total,
row_number() OVER (PARTITION BY user_id ORDER BY created_at) AS rn,
lag(total, 1) OVER (PARTITION BY user_id ORDER BY created_at) AS prev_total
FROM app.orders;
JSON / JSONB
-- Extraction
SELECT profile->>'company' AS company FROM app.users;
SELECT profile->'address'->>'city' FROM app.users;
-- Index pour les requêtes jsonb
CREATE INDEX users_profile_company_gin ON app.users USING gin ((profile->>'company'));
-- Existence / containment
SELECT * FROM app.users WHERE profile ? 'company'; -- la clé existe
SELECT * FROM app.users WHERE profile @> '{"role":"admin"}'; -- contient
-- Mise à jour jsonb
UPDATE app.users
SET profile = jsonb_set(COALESCE(profile,'{}'::jsonb), '{prefs,theme}', '"dark"', true);
Tableaux (Arrays)
-- appartenance et containment
SELECT * FROM app.users WHERE 'vip' = ANY(tags);
SELECT * FROM app.users WHERE tags @> ARRAY['beta'];
-- ajout
UPDATE app.users SET tags = array_distinct(tags || ARRAY['vip']);
Temps et dates
SELECT now() AT TIME ZONE 'Australia/Melbourne';
SELECT date_trunc('day', created_at) AS d, count(*)
FROM app.users GROUP BY d ORDER BY d;
-- Intervalles
SELECT now() - interval '7 days';
Transactions et verrous
BEGIN;
UPDATE app.accounts SET balance = balance - 100 WHERE id = 1;
UPDATE app.accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- ou ROLLBACK
-- Niveau d'isolement
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Vérifier les verrous
SELECT * FROM pg_locks l JOIN pg_stat_activity a USING (pid);
Rôles et permissions
-- Créer un rôle/utilisateur
CREATE ROLE app_user LOGIN PASSWORD 'secret';
GRANT USAGE ON SCHEMA app TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app TO app_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
Import / Export
-- Côté serveur (nécessite un superutilisateur ou des privilèges appropriés)
COPY app.users TO '/tmp/users.csv' CSV HEADER;
COPY app.users(email,name) FROM '/tmp/users.csv' CSV HEADER;
-- Côté client (psql)
\copy app.users TO 'users.csv' CSV HEADER
\copy app.users(email,name) FROM 'users.csv' CSV HEADER
Performance et observabilité
EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT ...; -- temps d'exécution réel
-- Vues de statistiques
SELECT * FROM pg_stat_user_tables;
SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 20; -- nécessite une extension
-- Maintenance
VACUUM [FULL] [VERBOSE] nom_table;
ANALYZE nom_table;
REINDEX TABLE nom_table;
Pour une vue d’ensemble plus large des outils essentiels pour les développeurs, y compris Docker, Git et PostgreSQL, consultez Outils pour développeurs : Le guide complet des flux de travail de développement modernes.
Activez les extensions selon les besoins :
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS btree_gin;
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- recherche par trigrammes
Recherche full-text (rapide)
ALTER TABLE app.docs ADD COLUMN tsv tsvector;
UPDATE app.docs SET tsv = to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,''));
CREATE INDEX docs_tsv_idx ON app.docs USING gin(tsv);
SELECT id FROM app.docs WHERE tsv @@ plainto_tsquery('english', 'quick brown fox');
Si vous hésitez entre une recherche native Postgres et une pile de recherche séparée, cette comparaison entre la recherche full-text PostgreSQL et Elasticsearch détaille les compromis.
Paramètres psql utiles
\pset pager off -- désactiver le pagin
\pset null '∅'
\pset format aligned -- autres : unaligned, csv
\set ON_ERROR_STOP on
\timing on
Requêtes utiles sur le catalogue
-- Taille des tables
SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) AS size
FROM pg_catalog.pg_statio_user_tables ORDER BY pg_total_relation_size(relid) DESC;
-- Gonflement des index (approximatif)
SELECT schemaname, relname, indexrelname, idx_scan
FROM pg_stat_user_indexes ORDER BY idx_scan ASC NULLS FIRST LIMIT 20;
Sauvegarde / Restauration
# Dump logique
pg_dump -h HÔTE -U UTILISATEUR -d SDB -F c -f db.dump # format personnalisé
pg_restore -h HÔTE -U UTILISATEUR -d NEW_DB -j 4 db.dump
# SQL brut
pg_dump -h HÔTE -U UTILISATEUR -d SDB > dump.sql
psql -h HÔTE -U UTILISATEUR -d SDB -f dump.sql
Pour les outils de gestion de base de données avec interface graphique, consultez DBeaver vs Beekeeper - Outils de gestion de base de données SQL et Installer DBeaver sur Linux - Tutoriel.
Réplication (vue d’ensemble)
- Les fichiers WAL sont diffusés du primaire vers le standby
- Paramètres clés :
wal_level,max_wal_senders,hot_standby,primary_conninfo - Outils :
pg_basebackup,standby.signal(PG ≥12)
Pièges et astuces
- Utilisez toujours
jsonbet nonjsonpour l’indexation et les opérateurs. - Préférez
timestamptz(prise en charge de la fuseau horaire). DISTINCT ONest la solution idéale de Postgres pour le “top-N par groupe”.- Utilisez
GENERATED ALWAYS AS IDENTITYau lieu deserial. - Évitez
SELECT *dans les requêtes de production. - Créez des index pour les filtres sélectifs et les clés de jointure.
- Mesurez avec
EXPLAIN (ANALYZE)avant d’optimiser.
Petites touches spécifiques à la version (≥v12+)
-- Identité générée
CREATE TABLE t (id bigINT GENERATED ALWAYS AS IDENTITY, ...);
-- UPSERT avec index partiel
CREATE UNIQUE INDEX ON t (key) WHERE is_active;