Erreur PostgreSQL : column does not exist
ERROR: column "createdat" does not exist
LINE 1: SELECT createdAt FROM users;
^
HINT: Perhaps you meant to reference the column "users.createdAt".
PostgreSQL n'a pas pu résoudre un nom de colonne — et très souvent le HINT vous en dit déjà la raison. Regardez l'exemple : la requête dit createdAt, l'erreur dit « createdat », le hint propose « users.createdAt ». C'est la règle du repli en minuscules à l'œuvre.
Ce que signifie cette erreur
Deux règles SQL produisent la quasi-totalité de ces erreurs :
- Les identifiants sans guillemets se replient en minuscules. Une colonne créée en tant que
"createdAt"(entre guillemets — les ORM et outils graphiques adorent faire cela) ne peut être référencée que par"createdAt". Sans guillemets,createdAtsignifiecreatedat, un nom différent. - Les guillemets doubles délimitent les identifiants, les guillemets simples délimitent les chaînes.
WHERE name = "alice"ne compare pas à la chaîne 'alice' — il cherche une colonne appeléealice, et échoue avec exactement cette erreur.
Causes fréquentes
- Colonne à casse mixte créée avec des guillemets, référencée sans (ou vice versa).
- Guillemets doubles utilisés pour un littéral de chaîne — l'indice révélateur étant que la « colonne manquante » est une valeur de donnée.
- Un alias de SELECT utilisé dans
WHERE: les alias n'y sont pas visibles (la clause WHERE est évaluée avant la liste de sélection).SELECT price * qty AS total ... WHERE total > 100échoue. - Dérive de schéma : la colonne n'existe réellement pas dans cet environnement parce qu'une migration n'a pas été exécutée.
Comment la diagnostiquer
\d users -- noms et casse EXACTS des colonnes
Comparez caractère par caractère, casse comprise. Si la requête est générée par un ORM, journalisez le SQL réel — les guillemets que l'ORM émet racontent toute l'histoire.
Comment la corriger
- Problème de casse → mettez-le entre guillemets exactement (
"createdAt") — ou mettez fin à la douleur définitivement :
Des identifiants en snake_case minuscule, jamais entre guillemets, sont la convention qui évite entièrement cette classe de bugs.ALTER TABLE users RENAME COLUMN "createdAt" TO created_at; - Littéral de chaîne → guillemets simples :
WHERE name = 'alice'. - Alias dans WHERE → répétez l'expression, ou enveloppez la requête :
SELECT * FROM (SELECT price * qty AS total ...) t WHERE total > 100.
🔍
Mêmes règles, version table : relation does not exist — search_path et identifiants entre guillemets.
