web-dev-qa-db-ja.com

エラー42P01:関係が存在しません

私はデータベースを作成するのが初めてで、このエラーは私を驚かせました。私はDB管理者のことを非常によく知っているためです(ほとんどの場合、レポートタイプのクエリを実行します)。 pgAdmin3 GUIを使用して新しいデータベースを作成し、SQLを使用してそこにDBオブジェクトを作成しようとしていますが、次のようになります。

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

マニュアルを確認しましたが、あまり役に立たなかったのですが、search_pathと何らかの関係があるのではないかと思います。こちらがスクリーンショットです。私が間違っていることについて何か考えはありますか?

42P01

9
Phrancis

schemasではなく、-tablesの場合、元々正しい構文でした。テーブル(エラーメッセージでは「リレーション」と呼ばれています)がないため、見つからないエラーが発生しました。

すでにお気づきのことと思いますが、私たち自身の間違いを修正する以外に方法はありません。

しかし、他にもあります。上記で行っていることは、一方では多すぎ、他方では不十分です。

スクリプトを実行すると、

  1. スキーマを作成する
  2. 役割を作成する
  3. grant SELECTスキーマ内のすべてのテーブル上(1.)で作成されたこの新しいロールに_
  4. 最後に、新しいスキーマに対するすべての権限(CREATEおよびUSAGE)を新しいロールに付与します

問題はポイント(3.)内にあります。replaysのテーブルに対する権限を付与しましたが、そこにテーブルがありません!将来的にはいくつか存在する可能性がありますが、この時点ではスキーマは完全に空です。このように、(3。)のGRANTは何もしません-この方法では、やりすぎです。

しかし、将来のテーブルはどうですか?

それらをカバーするためのコマンドがあります: ALTER DEFAULT PRIVILEGES 。これはテーブルだけでなく、以下にも適用されます。

現在[9.4以降]、変更できるのは、テーブル(ビューと外部テーブルを含む)、シーケンス、関数、およびタイプ(ドメインを含む)の特権のみです。

重要な制限が1つあります。

自分または自分がメンバーであるロールによって作成されるオブジェクトに対してのみ、デフォルトの権限を変更できます。

つまり、aliceによって作成されたテーブルであり、あなたもあなたのメンバーであるロールでもない(たとえば、psql\duを使用して確認できます) 、所定のアクセス権を取得しません。オプションのFOR ROLE句は、メンバーである「テーブル作成者」の役割を指定するために使用されます。多くの場合、これは、mydatabase_ownerのように、同じロールを使用してすべてのデータベースオブジェクトを作成することをお勧めします。

これを職場で示す小さな例:

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 │                   │ 

ご覧のとおり、aliceには、後者のテーブルに対する明示的な権限がありません。 (この場合、彼女はテーブルからSELECTを引き続きpublic疑似ロールのメンバーにすることができますが、public。)

5
dezso

私は答えを見つけるのを手伝ってくれた人と話しました。正しい構文は、後で参照する人のためにあります。 documentation はそれについて言及していますが、見落としがちです。

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