Bagaimana cara menghindari ketergantungan siklik (referensi melingkar) antara 3 tabel?


10

Saya punya 3 tabel:

  • Orang-orang
  • Pos
  • Suka

Ketika saya mendesain model ER itu memiliki ketergantungan siklik:

         1: N
Orang-orang -------- <Posting

         1: N
Posting ---------- <Suka

         1: N
Orang -------- <Suka

Logikanya adalah:

  • 1 orang dapat memiliki banyak posting.

  • 1 pos memiliki banyak suka.

  • 1 orang dapat menyukai banyak posting (orang yang dibuat tidak dapat menyukai postingnya sendiri).

Bagaimana saya bisa menghapus desain siklus semacam ini? Atau apakah desain db saya salah?

Jawaban:


10

Peraturan bisnis

Biarkan kami membuat beberapa penghargaan terhadap aturan bisnis yang telah Anda sampaikan:

  • A Personmenciptakan nol-satu-atau-banyak Posts .
  • A Postmenerima nol-satu-atau-banyak Likes .
  • Sebuah Personmemanifestasikan nol-satu-atau-banyak Likes , masing-masing Wich diajukan Popper terkait dengan satu tertentu Post .

Model logis

Kemudian, dari serangkaian asersi seperti itu, saya telah mendapatkan dua model data IDEF1X [1] tingkat logis yang ditunjukkan pada Gambar 1 .

Gambar 1 - Model Data Orang dan Posting

Opsi A

Seperti yang dapat Anda lihat dalam model Opsi A, PersonId bermigrasi [2] dari Personmenjadi Postsebagai KUNCI LUAR NEGERI (FK), tetapi ia menerima nama peran [3] dari AuthorId, dan atribut ini membentuk, bersama dengan PostNumber, KUNCI UTAMA (PK) dari Postjenis entitas.

Saya berasumsi bahwa Likehanya bisa eksis sehubungan dengan tertentu Post, jadi saya telah menetapkan suatu LikePK yang terdiri dari tiga atribut yang berbeda: PostAuthorId, PostNumberdan LikerId. Kombinasi PostAuthorIddan PostNumbermerupakan FK yang membuat referensi yang tepat untuk PostPK. LikerIdadalah, pada gilirannya, sebuah FK yang membentuk asosiasi yang sesuai dengan Person.PersonId.

Dengan bantuan struktur ini, Anda memastikan bahwa orang yang ditentukan hanya dapat memanifestasikan Likekejadian tunggal ke kejadian yang sama Post.

Metode untuk mencegah seorang Penulis Tulisan menyukai postingannya sendiri

Karena Anda tidak ingin membolehkan kemungkinan seseorang dapat menyukai tulisannya, begitu dalam fase implementasi, Anda harus membuat metode yang membandingkan nilai Like.PostAuthorIddengan nilai Like.LikerIddalam setiap upaya INSERT. Jika nilai-nilai tersebut cocok, (a) Anda menolak penyisipan, jika tidak cocok (b) Anda membiarkan prosesnya berlanjut.

Untuk menyelesaikan tugas ini di basis data Anda, Anda dapat menggunakan:

  1. Sebuah CONSTRAINT TARIF tapi, tentu saja, metode ini tidak termasuk MySQL, karena belum dilaksanakan di platform ini sejauh ini, seperti yang Anda lihat di sini dan di sini .

  2. Baris kode di dalam Transaksi ACID .

  3. Baris kode dalam TRIGGER , yang dapat mengembalikan pesan khusus yang menunjukkan upaya pelanggaran aturan.

Opsi B

Jika penulis bukan atribut yang mengidentifikasi dengan cara utama sebuah posting di domain bisnis Anda, Anda bisa menggunakan struktur yang mirip dengan yang digambarkan dalam Opsi B.

Pendekatan ini juga memastikan bahwa suatu posting hanya dapat disukai oleh orang yang sama satu kali saja.


Catatan

1. Definisi Integrasi untuk Pemodelan Informasi ( IDEF1X ) adalah teknik pemodelan data yang sangat direkomendasikan yang didefinisikan sebagai standar pada bulan Desember 1993 oleh Institut Standar dan Teknologi Nasional ( NIST ) Amerika Serikat .

2. IDEF1X mendefinisikan migrasi kunci sebagai “Proses pemodelan menempatkan kunci primer dari entitas induk atau generik pada entitas anak atau kategorinya sebagai kunci asing”.

3. Nama peran adalah denotasi yang diberikan pada atribut kunci asing untuk mengekspresikan makna atribut tersebut dalam konteks jenis entitas yang sesuai. Penamaan peran direkomendasikan sejak 1970 oleh Dr. EF Codd dalam makalah seminalnya yang berjudul “Model Data Relasional untuk Bank Data Bersama Besar” . Untuk bagiannya, IDEF1X — menjaga kesetiaan mengenai praktik relasional — juga mendukung prosedur ini.


6

Saya tidak melihat apa pun menjadi siklik di sini. Ada orang dan pos dan dua hubungan independen antara entitas ini. Saya akan melihat suka sebagai implementasi dari salah satu hubungan ini.

  • Seseorang dapat menulis banyak posting, sebuah posting ditulis oleh satu orang: 1:n
  • Seseorang bisa seperti banyak posting, posting dapat disukai oleh banyak orang: n:m
    The n: Hubungan m dapat diimplementasikan dengan relasi lain: likes.

Implementasi dasar

Implementasi dasar dapat terlihat seperti ini di PostgreSQL :

CREATE TABLE person (
  person_id serial PRIMARY KEY
, person    text NOT NULL
);

CREATE TABLE post (
  post_id   serial PRIMARY KEY
, author_id int NOT NULL  -- cannot be anonymous
     REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE  -- 1:n relationship
, post      text NOT NULL
);

CREATE TABLE likes (  -- n:m relationship
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE
, PRIMARY KEY (post_id, person_id)
);

Perhatikan khususnya bahwa pos harus memiliki penulis ( NOT NULL), sedangkan keberadaan suka adalah opsional. Untuk orang seperti yang ada, bagaimanapun, postdan person harus baik direferensikan (ditegakkan oleh PRIMARY KEYyang membuat kedua kolom NOT NULLsecara otomatis (Anda bisa menambahkan kendala tersebut secara eksplisit, berlebihan) sehingga orang-orang seperti anonim juga tidak mungkin.

Detail untuk implementasi n: m:

Cegah seperti diri sendiri

Anda juga menulis:

(orang yang dibuat tidak dapat menyukai posnya sendiri).

Itu belum diberlakukan dalam implementasi di atas, belum. Anda bisa menggunakan pemicu .
Atau salah satu dari solusi yang lebih cepat / lebih andal ini:

Rock-solid dengan biaya

Jika perlu rock-solid , Anda bisa memperpanjang FK dari likeske postuntuk menyertakan author_idberlebihan. Kemudian Anda bisa mengesampingkan inses dengan CHECKkendala sederhana .

CREATE TABLE likes (
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int 
, author_id int NOT NULL
, CONSTRAINT likes_pkey PRIMARY KEY (post_id, person_id)
, CONSTRAINT likes_post_fkey FOREIGN KEY (author_id, post_id)
     REFERENCES post(author_id, post_id) ON UPDATE CASCADE ON DELETE CASCADE
, CONSTRAINT no_self_like CHECK (person_id <> author_id)
);

Ini membutuhkanUNIQUE kendala yang sebaliknya juga berlebihan dalam post:

ALTER TABLE post ADD CONSTRAINT post_for_fk_uni UNIQUE (author_id, post_id);

Saya menempatkan author_idpertama untuk menyediakan indeks yang bermanfaat saat berada di sana.

Jawaban terkait dengan lebih banyak:

Lebih murah dengan CHECKkendala

Membangun "Implementasi dasar" di atas.

CHECKkendala dimaksudkan untuk tidak berubah. Merujuk tabel lain untuk pemeriksaan tidak pernah berubah, kami sedikit menyalahgunakan konsep ini di sini. Saya menyarankan untuk mendeklarasikan kendala NOT VALIDuntuk mencerminkan hal itu dengan benar. Detail:

Sebuah CHECKkendala tampaknya masuk akal dalam kasus ini, karena penulis posting tampaknya seperti atribut yang tidak pernah berubah. Larang pembaruan ke bidang itu untuk memastikan.

Kami palsu sebuah IMMUTABLEfungsi:

CREATE OR REPLACE FUNCTION f_author_id_of_post(_post_id int)
  RETURNS int AS
'SELECT p.author_id FROM public.post p WHERE p.post_id = $1'
LANGUAGE sql IMMUTABLE;

Ganti 'publik' dengan skema sebenarnya dari tabel Anda.
Gunakan fungsi ini dalam CHECKbatasan:

ALTER TABLE likes ADD CONSTRAINT no_self_like_chk
   CHECK (f_author_id_of_post(post_id) <> person_id) NOT VALID;

4

Saya pikir Anda mengalami kesulitan mencari tahu ini karena cara Anda menyatakan aturan bisnis Anda.

Orang dan Posting adalah "objek". Seperti adalah kata kerja.

Anda hanya memiliki 2 tindakan:

  1. Seseorang dapat membuat satu posting atau lebih
  2. Banyak orang dapat menyukai banyak posting. (kompilasi dari 2 pernyataan terakhir Anda)

orang menyukai diagram tulisan

Tabel "suka" akan memiliki person_id dan post_id sebagai kunci utama.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.