3 tablo arasında döngüsel bağımlılık (dairesel referans) nasıl önlenir?


10

3 tablom var:

  • İnsanlar
  • İleti
  • Seviyor

ER modelini tasarladığımda döngüsel bir bağımlılığı var:

         1: N-
İnsanlar -------- <Post

         1: N-
Mesaj ---------- <Beğeniler

         1: N-
İnsanlar -------- <Beğeniler

Mantık:

  • 1 kişinin birçok yayını olabilir.

  • 1 yayında birçok beğeni var.

  • 1 kişi birçok gönderiyi beğenebilir (oluşturulan kişi kendi gönderisini beğenemez).

Bu tür döngüsel tasarımı nasıl kaldırabilirim? Yoksa benim db tasarım yanlış mı?

Yanıtlar:


10

İş kuralları

Sunduğunuz iş kurallarına bazı değişiklikler yapalım:

  • Bir Personyaratır sıfır bir olarak veya çoğa Posts .
  • A Post, sıfır bir ya da çok alır Likes .
  • Bir Personbelirteç, sıfır-bir-veya-çok gösterir Likes , her biri bir spesifik ile ilgilidir Post.

Mantıksal modeller

Daha sonra, bu tür iddialardan, Şekil 1'de gösterilen iki mantıksal seviye IDEF1X [1] veri modelini türettim .

Şekil 1 - Kişiler ve Yayınlar Veri Modelleri

Seçenek A

Eğer A seçeneği modelinde görüldüğü gibi, PersonId göç [2] ile ilgili Personüzere Post, ancak alan bir yabancı anahtar (FK) olarak rol adı [3] bir AuthorIdile birlikte, ve bu özellik yapar PostNumber, birincil anahtar (PK) bir Postvarlık türü.

Ben varsayalım Likesadece belirli bağlantılı olarak var olabilir PostBen kurdunuz yüzden Like: üç farklı özelliklerin içermektedir PK PostAuthorId, PostNumberve LikerId. Kombinasyonu PostAuthorIdve PostNumberuygun referans yapan FK olan PostPK. LikerIdbuna karşılık olarak uygun bir ilişki kuran bir FK'dir Person.PersonId.

Bu yapının yardımıyla, kararlı bir kişinin Likeaynı Postörneğe sadece tek bir olay gösterebilmesini sağlarsınız.

Bir Yazı Yazarının kendi Yazılarını beğenmesini engelleme yöntemleri

Eğer bu yana yok bir kişinin onun gibi olabilir ihtimalini izin vermek istediğiniz uygulama aşamasında, sen değerini karşılaştıran bir yöntem belirlemelidir kez / onu, mesajları kaleme Like.PostAuthorIddeğeriyle Like.LikerIdher INSERT girişiminde. Bahsedilen değerler eşleşirse, (a) eklemeyi reddedersiniz, eşleşmezlerse (b) işlemin devam etmesine izin verirsiniz.

Veritabanınızda bu görevi gerçekleştirmek için aşağıdakilerden faydalanabilirsiniz:

  1. Bir CHECK CONSTRAINT ancak tabii ki bu yöntem MySQL'i hariç tutar, çünkü burada ve burada görebileceğiniz gibi şimdiye kadar bu platformda uygulanmamıştır .

  2. Bir ACID İşlemi içindeki kod satırları .

  3. Kural ihlali girişimini belirten özel bir ileti döndürebilen bir TRIGGER içindeki kod satırları .

Seçenek B

Yazar, işletme alan adınızdaki bir gönderiyi birincil şekilde tanımlayan bir özellik değilse, Seçenek B'de gösterilene benzer bir yapıya sahip olabilirsiniz.

Bu yaklaşım aynı zamanda bir gönderinin aynı kişi tarafından yalnızca bir kez beğenilebilmesini sağlar.


notlar

1. Bilgi Modellemesi için Entegrasyon Tanımı ( IDEF1X ), Aralık 1993'te Amerika Birleşik Devletleri Ulusal Standartlar ve Teknoloji Enstitüsü ( NIST ) tarafından standart olarak tanımlanan oldukça tavsiye edilen bir veri modelleme tekniğidir .

2. IDEF1X, anahtar taşımasını “Bir üst veya genel varlığın birincil anahtarını alt veya kategori varlığına yabancı anahtar olarak yerleştirmenin modelleme süreci” olarak tanımlar .

3. Rol adı , söz konusu özelliğin anlamını karşılık gelen varlık türü bağlamında ifade etmek için yabancı anahtar özelliğine atanan bir ifadedir. Rol adlandırma 1970'den beri Dr. EF Codd tarafından “Büyük Paylaşılan Veri Bankaları için İlişkisel Veri Modeli” başlıklı makalesinde önerilmektedir . Kendi adına, IDEF1X - ilişkisel uygulamalara sadık kalmak - bu prosedürü de savunuyor.


6

Burada döngüsel bir şey görmüyorum. Orada insanlar ve mesajlar bu varlıklar arasındaki iki bağımsız ilişkiler. Beğenileri bu ilişkilerden birinin uygulanması olarak görüyorum .

  • Bir kişi birçok yazı yazabilir, bir yazı bir kişi tarafından yazılır: 1:n
  • Bir kişi bir post çok beğenilmiş olabilir, birçok mesajları beğenebilir: n:m
    n: m ilişki başka ilişki ile uygulanabilir: likes.

Temel uygulama

Temel uygulama PostgreSQL'de şöyle görünebilir :

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

Özellikle, bir gönderinin bir yazarının ( ) olması gerektiğineNOT NULL dikkat edin, beğenilerin varlığı isteğe bağlıdır. Ancak mevcut beğeniler için postve person her ikisine de başvurulması gerekir ( PRIMARY KEYher iki sütunu NOT NULLotomatik olarak yapan tarafından zorunlu kılınmalıdır (bu kısıtlamaları açıkça, gereksiz olarak ekleyebilirsiniz), böylece anonim beğeniler de imkansızdır.

N: m uygulaması için ayrıntılar:

Kendine benzemeyi önle

Ayrıca şunu da yazdınız:

(yaratılan kişi kendi görevinden hoşlanamaz).

Bu yukarıdaki uygulamada henüz uygulanmıyor. Bir tetikleyici kullanabilirsiniz .
Veya bu daha hızlı / daha güvenilir çözümlerden biri:

Bir maliyet için kaya gibi sağlam

Kaya gibi sağlam olması gerekiyorsa , FK'yi fazladan dahil likesetmek postiçin genişletebilirsiniz author_id. O zaman ensesti basit bir CHECKkısıtlamayla dışlayabilirsiniz.

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

Bu , başka bir şekilde de gereksiz UNIQUEkısıtlama gerektirirpost :

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

author_idİlk sırada, yararlı bir dizin sağlamak için koydum .

Daha fazlası ile ilgili cevap:

CHECKKısıtlı olarak daha ucuz

Yukarıdaki "Temel uygulama" üzerine inşa.

CHECKkısıtlamalar değişmezdir. Bir kontrol için diğer tablolara başvurmak asla değişmez değildir, burada kavramı biraz kötüye kullanıyoruz. Bunu NOT VALIDdoğru bir şekilde yansıtması için kısıtlamayı beyan etmenizi öneririm . Detaylar:

CHECKBu özel durumda bir kısıtlama makul görünmektedir, çünkü bir yazının yazarı asla değişmeyen bir özellik gibi görünmektedir. Emin olmak için bu alandaki güncellemelere izin vermeyin.

Bir işlevi taklit ediyoruz IMMUTABLE:

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;

'Herkese açık' ifadesini tablolarınızın gerçek şemasıyla değiştirin.
Bu işlevi bir CHECKkısıtlamayla kullanın :

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

4

İş kurallarınızı nasıl belirlediğiniz nedeniyle bunu anlamakta zorluk çektiğinizi düşünüyorum.

İnsanlar ve Yayınlar "nesneler" dir. Tıpkı bir fiildir.

Gerçekten sadece 2 işleminiz var:

  1. Bir kişi bir veya daha fazla gönderi oluşturabilir
  2. Birçok kişi birçok gönderiyi beğenebilir. (son 2 ifadenizin bir derlemesi)

gönderiler diyagramı gibi insanlar

"Beğeniler" tablosunda birincil anahtar olarak person_id ve post_id olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.