web-dev-qa-db-fra.com

Erreur 42P01: la relation n'existe pas

Je suis nouveau dans la création de bases de données, et cette erreur m'a stupéfait, car je suis super nouveau avec les choses d'administration DB (je fais surtout des rapports sur les requêtes de type). J'ai créé une nouvelle base de données via l'interface graphique pgAdmin3, et j'essaie de créer des objets de base de données à l'aide de SQL, mais j'obtiens un:

ERROR: relation "replays" does not exist
SQL state: 42P01

J'ai parcouru le manuel, mais je n'ai rien trouvé de très utile, même si je soupçonne que cela a à voir avec search_path en quelque sorte. Voici une capture d'écran. Une idée de ce que je fais mal s'il vous plait?

42P01

9
Phrancis

Ce que vous aviez à l'origine était une syntaxe correcte - pour les tables , pas pour les schémas . Comme vous n'aviez pas de table (surnommée "relation" dans le message d'erreur), elle a renvoyé l'erreur introuvable.

Je vois que vous l'avez déjà remarqué - je crois qu'il n'y a pas de meilleure façon d'apprendre que de corriger nos propres erreurs;)

Mais il y a quelque chose de plus. Ce que vous faites ci-dessus est trop d'une part et pas assez d'autre part.

En exécutant le script, vous

  1. créer un schéma
  2. créer un rôle
  3. accorder SELECT sur toutes les tables du schéma créées dans (1.) à ce nouveau rôle_
  4. et, enfin, accordez tous les privilèges (CREATE et USAGE) sur le nouveau schéma au nouveau rôle

Le problème réside dans le point (3.) Vous avez accordé des privilèges sur les tables dans replays - mais il n'y a pas de tables dedans! Il pourrait y en avoir à l'avenir, mais à ce stade, le schéma est complètement vide. De cette façon, le GRANT dans (3.) ne fait rien - de cette façon, vous en faites trop.

Mais qu'en est-il des futures tables?

Il existe une commande pour les couvrir: ALTER DEFAULT PRIVILEGES . Cela s'applique non seulement aux tableaux, mais:

Actuellement [à partir de 9.4] , seuls les privilèges pour les tables (y compris les vues et les tables étrangères), les séquences, les fonctions et les types (y compris les domaines) peuvent être modifié.

Il existe également une limitation importante:

Vous ne pouvez modifier les privilèges par défaut que pour les objets qui seront créés par vous-même ou par les rôles dont vous êtes membre.

Cela signifie qu'une table créée par alice, qui n'est ni vous ni un rôle dont vous êtes membre (peut être vérifiée, par exemple, en utilisant \du Dans psql ), ne prendra pas les droits d'accès prescrits. La clause facultative FOR ROLE Est utilisée pour spécifier le rôle de "créateur de table" dont vous êtes membre. Dans de nombreux cas, cela implique que c'est une bonne idée de créer tous les objets de base de données en utilisant le même rôle - comme mydatabase_owner.

Un petit exemple pour le montrer au travail:

CREATE ROLE test_owner; -- cannot log in
CREATE SCHEMA replays AUTHORIZATION test_owner;
GRANT ALL ON SCHEMA replays TO test_owner;

SET ROLE TO test_owner; -- here we change the context, 
                        -- so that the next statement is issued as the owner role

ALTER DEFAULT PRIVILEGES IN SCHEMA replays GRANT SELECT ON TABLES TO alice;

CREATE TABLE replays.replayer (r_id serial PRIMARY KEY);

RESET ROLE; -- changing the context back to the original role

CREATE TABLE replays.replay_event (re_id serial PRIMARY KEY);

-- and now compare the two

\dp replays.replayer
                                   Access privileges
 Schema  │   Name   │ Type  │       Access privileges       │ Column access privileges 
─────────┼──────────┼───────┼───────────────────────────────┼──────────────────────────
 replays │ replayer │ table │ alice=r/test_owner           ↵│ 
         │          │       │ test_owner=arwdDxt/test_owner │ 

\dp replays.replay_event
                               Access privileges
 Schema  │     Name     │ Type  │ Access privileges │ Column access privileges 
─────────┼──────────────┼───────┼───────────────────┼──────────────────────────
 replays │ replay_event │ table │                   │ 

Comme vous pouvez le voir, alice n'a aucun droit explicite sur cette dernière table. (Dans ce cas, elle peut toujours SELECT de la table, étant membre du pseudorole public, mais je ne voulais pas encombrer l'exemple en révoquant les droits de public.)

5
dezso

J'ai parlé à quelqu'un qui m'a aidé à trouver la réponse. La syntaxe correcte est, pour toute personne en référence future. Le documentation le mentionne, bien qu'il puisse être facile de le manquer.

START TRANSACTION;
DROP SCHEMA IF EXISTS replays CASCADE;
CREATE SCHEMA replays;
CREATE ROLE admins WITH
    PASSWORD 'changeme';
GRANT SELECT ON ALL TABLES IN SCHEMA replays TO PUBLIC;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA replays TO admins;
COMMIT;
2
Phrancis