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

Bagaimana cara menerapkan hubungan banyak ke banyak di PostgreSQL?

Pernyataan SQL DDL (bahasa definisi data) dapat terlihat seperti ini:

CREATE TABLE product (
  product_id serial PRIMARY KEY  -- implicit primary key constraint
, product    text NOT NULL
, price      numeric NOT NULL DEFAULT 0
);

CREATE TABLE bill (
  bill_id  serial PRIMARY KEY
, bill     text NOT NULL
, billdate date NOT NULL DEFAULT CURRENT_DATE
);

CREATE TABLE bill_product (
  bill_id    int REFERENCES bill (bill_id) ON UPDATE CASCADE ON DELETE CASCADE
, product_id int REFERENCES product (product_id) ON UPDATE CASCADE
, amount     numeric NOT NULL DEFAULT 1
, CONSTRAINT bill_product_pkey PRIMARY KEY (bill_id, product_id)  -- explicit pk
);

Saya membuat beberapa penyesuaian:

  • Hubungan n:m biasanya diimplementasikan oleh tabel terpisah - bill_product dalam hal ini.

  • Saya menambahkan serial kolom sebagai kunci primer pengganti . Di Postgres 10 atau yang lebih baru, pertimbangkan IDENTITY kolom sebagai gantinya. Lihat:

    • Mengganti nama tabel dengan aman menggunakan kolom kunci utama serial
    • Kolom tabel kenaikan otomatis
    • https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/

    Saya sangat merekomendasikan itu, karena nama suatu produk hampir tidak unik (bukan "kunci alami" yang bagus). Selain itu, menerapkan keunikan dan mereferensikan kolom dalam kunci asing biasanya lebih murah dengan integer 4-byte (atau bahkan bigint 8-byte ) dibandingkan dengan string yang disimpan sebagai text atau varchar .

  • Jangan gunakan nama tipe data dasar seperti date sebagai pengidentifikasi . Meskipun ini mungkin, ini adalah gaya yang buruk dan menyebabkan kesalahan dan pesan kesalahan yang membingungkan. Gunakan pengidentifikasi legal, huruf kecil, tanpa tanda kutip. Jangan pernah menggunakan kata-kata khusus dan hindari tanda kutip ganda jika Anda bisa.

  • "nama" bukanlah nama yang baik. Saya mengganti nama kolom tabel product menjadi product (atau product_name atau serupa). Itu adalah konvensi penamaan yang lebih baik . Jika tidak, saat Anda menggabungkan beberapa tabel dalam kueri - yang Anda lakukan banyak dalam database relasional - Anda berakhir dengan beberapa kolom bernama "nama" dan harus menggunakan alias kolom untuk menyelesaikan kekacauan. Itu tidak membantu. Anti-pola lain yang tersebar luas hanya "id" sebagai nama kolom.
    Saya tidak yakin apa nama bill akan menjadi. bill_id mungkin cukup dalam kasus ini.

  • price adalah tipe data numeric untuk menyimpan bilangan pecahan tepat seperti yang dimasukkan (tipe presisi sewenang-wenang alih-alih tipe floating point). Jika Anda berurusan dengan bilangan bulat secara eksklusif, buat integer . Misalnya, Anda dapat menyimpan harga sebagai Sen .

  • amount ("Products" dalam pertanyaan Anda) masuk ke tabel tautan bill_product dan bertipe numeric demikian juga. Sekali lagi, integer jika Anda berurusan dengan bilangan bulat secara eksklusif.

  • Anda melihat kunci asing di bill_product ? Saya membuat keduanya untuk mengalirkan perubahan:ON UPDATE CASCADE . Jika product_id atau bill_id harus berubah, perubahan tersebut mengalir ke semua entri yang bergantung di bill_product dan tidak ada yang rusak. Itu hanya referensi tanpa makna tersendiri.
    Saya juga menggunakan ON DELETE CASCADE untuk bill_id :Jika tagihan dihapus, detailnya ikut mati.
    Tidak demikian untuk produk:Anda tidak ingin menghapus produk yang digunakan dalam tagihan. Postgres akan membuat kesalahan jika Anda mencoba ini. Anda akan menambahkan kolom lain ke product untuk menandai baris usang ("soft-delete").

  • Semua kolom dalam contoh dasar ini berakhir menjadi NOT NULL , jadi NULL nilai tidak diperbolehkan. (Ya, semua kolom - kolom kunci utama didefinisikan UNIQUE NOT NULL otomatis.) Itu karena NULL nilai tidak akan masuk akal di salah satu kolom. Itu membuat hidup seorang pemula lebih mudah. Tapi Anda tidak akan lolos begitu saja, Anda perlu memahami NULL penanganan pula. Kolom tambahan mungkin mengizinkan NULL nilai, fungsi, dan gabungan dapat memperkenalkan NULL nilai dalam kueri dll.

  • Baca bab tentang CREATE TABLE dalam manual.

  • Kunci utama diimplementasikan dengan indeks yang unik pada kolom kunci, yang membuat kueri dengan kondisi pada kolom PK menjadi cepat. Namun, urutan kolom kunci relevan dalam kunci multikolom. Sejak PK di bill_product ada di (bill_id, product_id) dalam contoh saya, Anda mungkin ingin menambahkan indeks lain hanya pada product_id atau (product_id, bill_id) jika Anda memiliki pertanyaan untuk mencari product_id yang diberikan dan tidak ada bill_id . Lihat:

    • Kunci utama komposit PostgreSQL
    • Apakah indeks komposit juga bagus untuk kueri di bidang pertama?
    • Kerja indeks di PostgreSQL
  • Baca bab tentang indeks di manual.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Konferensi Musim Semi FLOSS UK

  2. Jumlah SQL bersyarat

  3. Rails 4 session.id kadang nihil

  4. psql:FATAL:basis data <pengguna> tidak ada

  5. Cara Memperbarui Banyak Kolom di PostgreSQL