Fehler 42P01: Beziehung existiert nicht

9

Ich bin neu im Erstellen von Datenbanken, und dieser Fehler hat mich verblüfft, da ich mit DB-Administrator-Dingen sehr neu bin (ich mache meistens Berichts-Typ-Abfragen). Ich habe eine neue Datenbank über die pgAdmin3-GUI erstellt und versuche dort DB-Objekte mit SQL zu erstellen, erhalte jedoch Folgendes:

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

Ich habe das Handbuch durchgesehen, fand aber nichts sehr hilfreiches, obwohl ich vermute, dass es search_pathirgendwie damit zu tun hat . Hier ist ein Screenshot. Irgendeine Idee, was ich falsch mache, bitte?

42P01

Phrancis
quelle

Antworten:

5

Was Sie ursprünglich hatten, war eine korrekte Syntax - für Tabellen , nicht für Schemas . Da Sie keine Tabelle hatten (in der Fehlermeldung als "Beziehung" bezeichnet), wurde der nicht gefundene Fehler ausgegeben.

Ich sehe, dass Sie dies bereits bemerkt haben - ich glaube, es gibt keinen besseren Weg zu lernen, als unsere eigenen Fehler zu beheben;)

Aber es gibt noch etwas mehr. Was Sie oben tun, ist einerseits zu viel und andererseits nicht genug.

Führen Sie das Skript aus, Sie

  1. Erstellen Sie ein Schema
  2. eine Rolle erstellen
  3. gewähren SELECT auf alle Tabellen in dem Schema in (1) auf diese neue role_ erstellt
  4. und schließlich gewähren Sie der neuen Rolle alle Berechtigungen ( CREATEund USAGE) für das neue Schema

Das Problem liegt in Punkt (3.) Sie haben Berechtigungen für Tabellen in gewährt replays- aber es gibt dort keine Tabellen! Möglicherweise gibt es in Zukunft einige, aber zu diesem Zeitpunkt ist das Schema vollständig leer. Auf diese Weise macht das GRANTin (3.) nichts - auf diese Weise tun Sie zu viel.

Aber was ist mit den zukünftigen Tischen?

Es gibt einen Befehl, um sie abzudecken : ALTER DEFAULT PRIVILEGES. Dies gilt nicht nur für Tabellen, sondern auch für:

Derzeit [ab 9.4] können nur die Berechtigungen für Tabellen (einschließlich Ansichten und Fremdtabellen), Sequenzen, Funktionen und Typen (einschließlich Domänen) geändert werden.

Es gibt auch eine wichtige Einschränkung:

Sie können die Standardberechtigungen nur für Objekte ändern, die von Ihnen selbst oder von Rollen, denen Sie angehören, erstellt werden.

Dies bedeutet, dass eine Tabelle, die von erstellt wurde alice, von der weder Sie noch eine Rolle als Sie Mitglied sind (kann beispielsweise durch Verwendung von \duin überprüft werden psql), nicht die vorgeschriebenen Zugriffsrechte erhält. Die optionale FOR ROLEKlausel wird verwendet, um die Rolle des Tabellenerstellers anzugeben, in der Sie Mitglied sind. In vielen Fällen bedeutet dies, dass es eine gute Idee ist, alle Datenbankobjekte mit derselben Rolle zu erstellen mydatabase_owner.

Ein kleines Beispiel, um dies bei der Arbeit zu zeigen:

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                     

Wie Sie sehen können, alicehat keine explizite Rechte für die letztere Tabelle. (In diesem Fall kann sie immer noch SELECTvom Tisch, weil sie Mitglied der publicPseudorole ist, aber ich wollte das Beispiel nicht durch Widerruf der Rechte von überladen public.)

dezso
quelle
2

Ich habe mit jemandem gesprochen, der mir geholfen hat, die Antwort zu finden. Die richtige Syntax ist für jeden, auf den in Zukunft Bezug genommen wird. Die Dokumentation erwähnt es, obwohl es leicht zu übersehen sein kann.

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;
Phrancis
quelle