PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Batasan kunci asing dalam hubungan banyak-ke-banyak

Ini memohon masalah. Anda akan terus mengalami ketidaksesuaian kecil. Atau bahkan tidak menyadarinya sampai lama kemudian, ketika kerusakan terjadi. Jangan lakukan itu. Gunakan PostgreSQL secara lokal juga. Ini tersedia secara bebas untuk sebagian besar setiap OS. Untuk seseorang yang terlibat dalam "proyek kursus database" ini adalah kebodohan yang mengejutkan. Terkait:

Saran lainnya:

  • Seperti @Priidu disebutkan dalam komentar , batasan kunci asing Anda mundur. Ini bukan untuk diperdebatkan, mereka hanya salah .

  • Di PostgreSQL gunakan serial atau IDENTITY kolom (Postgres 10+) alih-alih SQLite AUTOINCREMENT . Lihat:

  • Gunakan timestamp (atau timestamptz ) bukannya datetime .

  • Jangan gunakan pengidentifikasi huruf besar-kecil.

  • Jangan gunakan nama kolom yang tidak deskriptif seperti id . Pernah. Itu anti-pola yang diperkenalkan oleh middleware setengah cerdas dan ORM. Saat Anda bergabung dengan beberapa tabel, Anda akan mendapatkan beberapa kolom dengan nama id . Itu sangat menyakitkan.

  • Ada banyak gaya penamaan, tetapi sebagian besar setuju bahwa lebih baik memiliki istilah tunggal sebagai nama tabel. Ini lebih pendek dan setidaknya intuitif/logis. label , bukan labels .

Semuanya disatukan, bisa terlihat seperti ini:

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)
);

Pemicu

Untuk menghapus label yang tidak digunakan, terapkan pemicu . Saya menyediakan versi lain karena saya tidak senang dengan yang disediakan oleh @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$;
  • Pemicu fungsi harus dibuat sebelum pemicu .

  • DELETE simple sederhana perintah dapat melakukan pekerjaan. Tidak diperlukan kueri kedua - khususnya tidak ada count(*) . EXISTS lebih murah.

  • Kutipan tunggal di sekitar nama bahasa ditoleransi, tetapi itu benar-benar pengidentifikasi, jadi hilangkan omong kosong: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();

Tidak ada CREATE OR REPLACE TRIGGER di PostgreSQL, belum. Cukup CREATE TRIGGER .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tabel terpotong Postgresql dengan batasan kunci asing

  2. Pertandingan Awalan Terpanjang

  3. daftar tipe Postgres ENUM

  4. menggunakan profil boot musim semi dengan atribut konteks liquibase changeset untuk mengelola ruang lingkup changset

  5. Apakah ada cara untuk menggunakan OrmLite dengan Postgres hstores?