Impossible d'utiliser simplement le nom de table PostgreSQL («la relation n'existe pas»)

195

J'essaie d'exécuter le script PHP suivant pour faire une simple requête de base de données:

$db_host = "localhost";
$db_name = "showfinder";
$username = "user";
$password = "password";
$dbconn = pg_connect("host=$db_host dbname=$db_name user=$username password=$password")
    or die('Could not connect: ' . pg_last_error());

$query = 'SELECT * FROM sf_bands LIMIT 10';
$result = pg_query($query) or die('Query failed: ' . pg_last_error());

Cela produit l'erreur suivante:

Échec de la requête: ERREUR: la relation "sf_bands" n'existe pas

Dans tous les exemples, je peux trouver où quelqu'un obtient une erreur indiquant que la relation n'existe pas, c'est parce qu'il utilise des lettres majuscules dans son nom de table. Le nom de ma table ne contient pas de lettres majuscules. Existe-t-il un moyen d'interroger ma table sans inclure le nom de la base de données, c'est showfinder.sf_bands-à- dire ?

Keyslinger
la source
2
Êtes-vous sûr que la table sf_bands existe? Est-ce que showfinder.sf_bands fonctionne?
brian-brazil
1
showfinder.sf_bands fonctionne parfaitement
Keyslinger
Peut-être devrais-je noter que ma base de données a été migrée de MySQL
Keyslinger
Pouvez-vous essayer pg_query ($ dbconn, $ query)? La connexion implicite peut entraîner des problèmes difficiles à déboguer, peut aussi bien l'éliminer comme un problème possible. Pouvez-vous également essayer pg_dbname ($ dbconn) pour vous assurer qu'il est bien connecté à showfinder?
brian-brazil
1
+1 pour avoir mentionné que les lettres majuscules sont le problème. J'ai passé une heure à essayer de comprendre pourquoi je ne pouvais pas sélectionner à partir d'une seule table dans PostgreSQL. Quel programme terrible.
Brain2000

Réponses:

314

D'après ce que j'ai lu, cette erreur signifie que vous ne référencez pas correctement le nom de la table. Une raison courante est que la table est définie avec une orthographe mixte et que vous essayez de l'interroger avec toutes les minuscules.

En d'autres termes, ce qui suit échoue:

CREATE TABLE "SF_Bands" ( ... );

SELECT * FROM sf_bands;  -- ERROR!

Utilisez des guillemets pour délimiter les identificateurs afin de pouvoir utiliser l'orthographe de casse mixte spécifique lorsque la table est définie.

SELECT * FROM "SF_Bands";

Concernant votre commentaire, vous pouvez ajouter un schéma au "search_path" de sorte que lorsque vous référencez un nom de table sans qualifier son schéma, la requête correspondra à ce nom de table en vérifiant chaque schéma dans l'ordre. Tout comme PATHdans le shell ou include_pathen PHP, etc. Vous pouvez vérifier votre chemin de recherche de schéma actuel:

SHOW search_path
  "$user",public

Vous pouvez modifier le chemin de recherche de votre schéma:

SET search_path TO showfinder,public;

Voir également http://www.postgresql.org/docs/8.3/static/ddl-schemas.html

Bill Karwin
la source
Oups, pardonne-moi. Je voulais dire que le nom de ma table n'a pas de majuscules, pas le nom de ma base de données.
Keyslinger
13
Il semble que même si vous tapez SELECT * FROM SF_Bandscela échouera toujours, car Postgres décide de minuscules ce nom de table pour vous. Bizarre ...
Roman Starkov
3
@romkyns: Oui, c'est en fait assez courant dans les marques de SGBDR, les identifiants non limités sont annoncés comme "insensibles à la casse". Mais ils ne sont pas vraiment insensibles à la casse, car la façon dont ils l'ont implémenté consiste à forcer les minuscules. Cela correspond au nom de la table uniquement si vous avez autorisé le nom de la table à être en minuscules lorsque vous avez défini la table. Si vous utilisez des délimiteurs entre guillemets lorsque vous CREATE TABLE, vous devez utiliser des délimiteurs lorsque vous le référencez dans les requêtes.
Bill Karwin
1
Postgres minuscule automatiquement les noms de table s'ils ne sont pas entre guillemets? C'est assez stupide ...
Andy
@Andy, lorsque vous écrivez votre propre base de données SQL, n'hésitez pas à implémenter des identifiants insensibles à la casse d'une autre manière. :)
Bill Karwin
78

J'ai eu des problèmes avec ça et voici l'histoire (triste mais vraie):

  1. Si le nom de votre table est tout en minuscules comme: comptes que vous pouvez utiliser: select * from AcCounTset cela fonctionnera bien

  2. Si le nom de votre table est tout en minuscules comme: accounts Ce qui suit échoue: select * from "AcCounTs"

  3. Si le nom de votre table est composé de casse mixte, par exemple: ce qui Accounts suit échouera: select * from accounts

  4. Si le nom de votre table est mixte comme: Accounts Ce qui suit fonctionnera bien: select * from "Accounts"

Je n'aime pas me souvenir de trucs inutiles comme ça mais tu dois le faire;)

Mitzi
la source
1
Idem pour les noms de colonnes dans les clauses where
Roland
8
5. Le cas mixte, comme Accounts, échouera avec select * from Accounts;je trouve la partie la plus étrange: le même cas n'est PAS identique.
Roland
9
Tout y est: tous les noms dans la requête postgres sont en minuscules, sauf si vous utilisez des guillemets.
Erndob
1
La quatrième option a fonctionné pour moi, même si je n'utilise pas PHP
Sayari
2
Merci d'avoir présenté toutes les interactions! :)
GetHacked
19

Requête de processus Postgres différente des autres SGBDR. Mettez le nom du schéma entre guillemets avant le nom de votre table comme ceci, "SCHEMA_NAME". "SF_Bands"

Ugur Artun
la source
7
Qu'est-ce que votre réponse ajoute à la réponse précédemment acceptée, votée 22 fois et avec beaucoup de détails?
Yaroslav
18

Mettez le paramètre dbname dans votre chaîne de connexion. Cela fonctionne pour moi alors que tout le reste a échoué.

Lors de la sélection, spécifiez également le fichier your_schema. your_tablecomme ça:

select * from my_schema.your_table
JarosPL
la source
1
Mettre le nom du schéma dans, par exemple my_schema.my_relation dans la requête a aidé.
JoeTidee
2
Merci beaucoup! Cela m'aide vraiment à résoudre le problème! Mais existe-t-il un moyen d'omettre le nom du schéma?
Charlotte
9

J'ai eu un problème similaire sur OSX mais j'ai essayé de jouer avec des guillemets doubles et simples. Pour votre cas, vous pouvez essayer quelque chose comme ça

$query = 'SELECT * FROM "sf_bands"'; // NOTE: double quotes on "sf_Bands"
enregistrer
la source
6

Vous devez écrire le nom du schéma et le nom de la table en marque de qutotation. Comme ci-dessous:

select * from "schemaName"."tableName";
kira
la source
5

C'est vraiment utile

SET search_path TO schema,public;

J'ai creusé davantage ces problèmes, et j'ai découvert comment définir ce "search_path" par defoult pour un nouvel utilisateur dans la base de données actuelle.

Ouvrez Propriétés de la base de données puis ouvrez la feuille «Variables» et ajoutez simplement cette variable pour votre utilisateur avec la valeur réelle.

Alors maintenant, votre utilisateur obtiendra ce nom_schéma par defoult et vous pourrez utiliser tableName sans schemaName.

Alexander Kuzichkin
la source
2

Pour moi, le problème était que j'avais utilisé une requête sur cette table particulière pendant que Django était initialisé. Bien sûr, il lancera alors une erreur, car ces tables n'existaient pas. Dans mon cas, c'était une get_or_createméthode dans un fichier admin.py, qui était exécutée chaque fois que le logiciel exécutait n'importe quel type d'opération (dans ce cas, la migration). J'espère que cela aide quelqu'un.

Özer S.
la source
2

La solution la plus simple consiste simplement à changer le nom de la table et tous les noms de colonne en minuscules et votre problème sera résolu.

Par exemple:

  • Changer Table_Nameen table_name et
  • Changer ColumnNamepourcolumnname
moiMadhav
la source
2

Si un nom de table contient des traits de soulignement ou des majuscules, vous devez l'entourer de guillemets doubles.

SELECT * from "Table_Name";
Steve Shipway
la source
0

Vous devez d'abord ajouter le schéma, par exemple

SELECT * FROM place.user_place;

Si vous ne souhaitez pas l'ajouter dans toutes les requêtes, essayez ceci:

SET search_path TO place;

Maintenant, cela fonctionnera:

SELECT * FROM user_place;
Alexis Gamarra
la source