sql >> データベース >  >> RDS >> PostgreSQL

多対多の関係における外部キーの制約

    これはトラブルを懇願しています。あなたはマイナーな非互換性に遭遇し続けるでしょう。または、損傷が発生するずっと後まで、それらに気付くことさえありません。 しないでください。 ローカルでもPostgreSQLを使用します。ほとんどすべてのOSで無料で利用できます。 「データベースコースプロジェクト」に携わっている人にとって、これは驚くべき愚かさです。関連:

    その他のアドバイス:

    • コメントで言及されている@Priiduとして 、外部キー制約は後方にあります。これは議論の余地がありません、彼らは単に間違っています

    • PostgreSQLではserialを使用します またはIDENTITY SQLite AUTOINCREMENTの代わりに列(Postgres 10+) 。参照:

    • timestampを使用します (またはtimestamptz datetimeの代わりに 。

    • 大文字と小文字が混在する識別子は使用しないでください。

    • idのようなわかりにくい列名は使用しないでください 。これまで。これは、半ばウィットのミドルウェアとORMによって導入されたアンチパターンです。いくつかのテーブルを結合すると、idという名前の複数の列ができあがります。 。それは積極的に害を及ぼします。

    • 多くの命名スタイルがありますが、ほとんどの場合、テーブル名として単一の用語を使用する方がよいことに同意しています。それはより短く、少なくとも直感的/論理的です。 labellabelsではありません 。

    すべてをまとめると、次のようになります。

    CREATE TABLE IF NOT EXISTS post (
       post_id   serial PRIMARY KEY
     , author_id integer
     , title     text
     , content   text
     , image_url text
     , date      timestamp
    );
    
    CREATE TABLE IF NOT EXISTS label (
       label_id  serial PRIMARY KEY
     , name      text UNIQUE
    );
    
    CREATE TABLE IF NOT EXISTS label_post(
        post_id  integer REFERENCES post(post_id) ON UPDATE CASCADE ON DELETE CASCADE
      , label_id integer REFERENCES label(label_id) ON UPDATE CASCADE ON DELETE CASCADE
      , PRIMARY KEY (post_id, label_id)
    );
    

    トリガー

    未使用のラベルを削除するには、トリガーを実装します 。 @Priiduが提供するバージョン に満足できないため、別のバージョンを提供します :

    CREATE OR REPLACE FUNCTION f_trg_kill_orphaned_label() 
      RETURNS trigger
      LANGUAGE plpgsql AS
    $func$
    BEGIN
       DELETE FROM label l
       WHERE  l.label_id = OLD.label_id
       AND    NOT EXISTS (
          SELECT 1 FROM label_post lp
          WHERE  lp.label_id = OLD.label_id
          );
    END
    $func$;
    
    • トリガー関数 前に作成する必要があります トリガー

    • 単純なDELETE コマンドは仕事をすることができます。 2番目のクエリは必要ありません-特にcount(*)は必要ありません 。 EXISTS 安いです。

    • 言語名を一重引用符で囲むことは許容されますが、実際には識別子であるため、ナンセンスを省略してください:LANGUAGE plpgsql

    CREATE TRIGGER label_post_delaft_kill_orphaned_label
    AFTER DELETE ON label_post
    FOR EACH ROW EXECUTE PROCEDURE f_trg_kill_orphaned_label();
    

    CREATE OR REPLACE TRIGGERはありません PostgreSQLではまだです。 CREATE TRIGGERだけ



    1. SQLクエリを1つの条件から複数の条件に変更する

    2. SQLローダー、トリガー飽和?

    3. php-mysqlはデータベースから次と前のIDをフェッチします

    4. テストフェーズの後に常に実行されるMavenフェーズはどれですか?