Errore PostgreSQL: relation does not exist
ERROR: relation "users" does not exist
LINE 1: SELECT * FROM users;
^
PostgreSQL non ha trovato alcuna tabella, view o sequence con quel nome tra gli schemi in cui gli è consentito guardare. In pratica questo errore raramente significa che la tabella manca — di solito significa che tu e PostgreSQL state guardando in posti diversi.
Cosa significa questo errore
"Relation" è il termine ombrello di PostgreSQL per tabelle, view, sequence, indici e affini. La risoluzione dei nomi dipende da due elementi di contesto che le persone dimenticano di avere: il database corrente (le relation vivono per-database; non esiste accesso cross-database) e la search_path, la lista ordinata di schemi rispetto a cui un nome non qualificato viene risolto.
Più una regola di sintassi che genera confusione senza fine: gli identificatori non quotati vengono convertiti in minuscolo. Una tabella creata come "Users" (quotata, da un ORM o una GUI) può essere raggiunta solo come "Users" — il nome non quotato users è un identificatore diverso.
Cause comuni
- La tabella è in uno schema non presente nella tua
search_path(es. èapp.userse il tuo path è"$user", public). - Identificatore con maiuscole miste creato con le virgolette; le query non quotate vengono convertite in minuscolo e non lo trovano.
- Database sbagliato — connesso al database di default
postgresinvece che a quello applicativo; tutto "scompare". - Migrazioni non applicate in questo ambiente, o applicate a uno schema diverso da quello che l'app interroga.
- Una tabella temporanea da un'altra sessione o una connessione precedente (le tabelle temp sono per-sessione).
Come diagnosticarlo
SELECT current_database();
SHOW search_path;
-- La relation esiste da qualche parte, sotto qualunque case?
SELECT n.nspname AS schema, c.relname, c.relkind
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname ILIKE '%users%';
Quest'ultima query risolve tutto in un colpo: ti dice se la relation esiste affatto, in quale schema e con quale case esatto.
Come risolverlo
- Schema sbagliato → qualifica il nome (
app.users) o imposta il path in modo persistente dove serve:
(AncheALTER ROLE app_user SET search_path = app, public; -- oppure: ALTER DATABASE appdb SET search_path = app, public;SET search_patha livello di sessione funziona, ma con i connection pooler preferisci le impostazioni a livello di ruolo/database.) - Maiuscole miste → quotalo esattamente (
SELECT * FROM "Users") — e adotta la convenzione che salva tutti: solo identificatori minuscoli e non quotati. - Database sbagliato → correggi la stringa di connessione;
psqlsenza un nome di database ti connette a uno che porta il nome del tuo utente OS, o apostgres— raramente ciò che usa l'app. - Migrazioni mancanti → eseguile; la query diagnostica qui sopra conferma se lo schema è davvero vuoto.
