Cascade (ON DELETE / UPDATE) davranışının iyi açıklaması


98

Her gün şema tasarlamıyorum, ancak yaptığım zaman, yönetimi kolaylaştırmak için kaskad güncellemeleri / silmeleri doğru kurmaya çalışıyorum. Cascade'lerin nasıl çalıştığını biliyorum ama hangi masanın hangisi olduğunu asla hatırlayamıyorum.

Örneğin, eğer iki tablo var - Parentve Childüzerinde yabancı bir anahtarla - Childbu referanslar Parentvardır ve ON DELETE CASCADEbir çağlayan tetikleyecek kaydeder ve hangi zinciri tarafından silinmiş olsun kaydeden? Benim ilk tahminim Childkayıtları ne zaman silinir Parentkayıtları silinir beri Childkayıtlar bağlıdır Parentkayıtları, ancak ON DELETEbelirsiz; o silmek anlamına gelebilir Parentzaman kaydını Childkayıt silinir, ya da silmek anlamına gelebilir Childzaman kaydını Parentsilinir. Peki hangisi?

Ben sözdizimi olsaydı ON PARENT DELETE, CASCADE, ON FOREIGN DELETE, CASCADEya belirsizliği kaldırmak için benzer bir şey. Bunu hatırlamak için anımsama yapan var mı?

Yanıtlar:


138

İsterseniz Parentve Childşartlar ve onlar hatırlanacak kolay hissetmek, sen çevirisini gibi olabilir ON DELETE CASCADEiçinLeave No Orphans!

Bu, bir Parentsatır silindiğinde (öldürüldüğünde), hiçbir yetim satırın Childmasaya canlı kalmamasını sağlar . Ebeveyn sırasının bütün çocukları da öldürülür (silinir). Bu çocuklardan herhangi birinin torunları varsa (başka bir yabancı anahtar aracılığıyla başka bir masada) ve ON DELETE CASCADEtanımlanmışsa, bunlar da öldürülmelidir (ve tanımlanmış bir kaskad etkisi olduğu sürece tüm torunlar).

FOREIGN KEYKısıtlama kendisi de tarif edilebilir Allow No Orphans!(ilk olarak). Hayır Childbu bir değil varsa hiç izin verilmelidir çocuk tablosundaki (yazılı) Parent(ana tablodaki bir satır).

Tutarlılık ON DELETE RESTRICTiçin, (daha az agresif) diline çevrilebilir. You Can't Kill Parents!Sadece çocuksuz satırlar öldürülebilir (silinebilir).


3
Analojide hala bir şeylerin eksik olduğunu hissediyorum. Bir çocuğun birden fazla ebeveyni olamaz mı? Bu durumda bir ebeveyni öldürmek çocuğu yetim kaldıracak mı?
Jus12

7
@ Jus12 Hayır, yabancı anahtar kısıtlamaları sadece 1 ebeveyn ile çalışır. Bu yönüyle ilgili iyi bir benzetme değil.
ypercubeᵀᴹ

1
@ypercube: Buna izin verilmiyor mu? Order(custID, itemID, orderID)buradaki tablodaki custIDbirincil anahtara ve Customerstablodaki birincil anahtara itemIDatıfta bulunur Items. Olmaz Orderiki ebeveyni?
Jus12

4
@ Jus12 Elbette izin var, ancak 2 yabancı anahtar kısıtlaması olacak. Sonra her çocuğun (emrin) bir ebeveyni (müşterisi) ve bir ebeveyni (kalemi) olur. 2 FK'in davranışları farklı olabilir. (Yani, örneğin, müşterileri öldürmek tüm (emir) çocuklarını öldürür, ancak eşyaları öldürmek emirlerini öldürmezdi.)
ypercubeᵀᴹ

1
"Öksüz" demezsek, ana analoji hala çalışabilir. Çocuk girişinde iki ayrı ebeveyne iki referans varsa, bu hala boşanmış bir çiftin çocuğu olarak görülebilir. Kısıtla: "Annemi öldürmene izin vermeyeceğim" Cascade: "Babamı öldürürsen, ben de öleceğim"
Christopher McGowan

31

Örneğin, iki tablom varsa - Ebeveyn ve Çocuk - Çocuk kayıtlarının Ebeveyn kayıtlarına ait olduğu yerlerde, hangi tablo ON DELETE CASCADE'e ihtiyaç duyar?

DELETE CASCADE, bir yabancı anahtar bildirgesinde isteğe bağlı bir maddedir. Böylece yabancı anahtar bildirimi ile gider . (Anlamı, "çocuk" tablosunda.)

... Çocuk kaydı silindiğinde Ebeveyn kaydının silinmesi anlamına gelebilir veya Çocuk kaydı silindiğinde Çocuk kaydının silinmesi anlamına gelebilir. Peki hangisi?

Yabancı anahtar bildirimini yorumlamanın bir yolu, "Bu sütun için geçerli tüm değerler" that_table "içindeki" that_column "ifadesinden gelir." "Çocuk" tablosundaki bir satırı sildiğinizde, kimse umursamıyor. Veri bütünlüğünü etkilemez.

"Parent" tablosundan bir satırı - "that_table" öğesinden sildiğinizde, "child" tablosu için olası değerlerden geçerli bir değeri kaldırırsınız. Veri bütünlüğünü korumak için, "çocuk" tablosuna bir şey yapmak zorundasınız . Basamaklı silmeler yapabileceğiniz bir şeydir.


2

SQL: 2011 Özellikleri

İçin beş seçenek vardır ON DELETEve ON UPDATEbunlar için de geçerlidir FOREIGN KEY. Bunlar <referential actions>doğrudan SQL: 2011 spec denir.

  • ON DELETE CASCADE: başvurulan tablonun bir satırı silinirse, başvuru tablosundaki tüm eşleşen satırlar silinir.
  • ON DELETE SET NULL: başvurulan tablonun bir satırı silinirse, başvuru tablonun tüm eşleşen satırlarındaki tüm referans sütunları null değerine ayarlanır.
  • ON DELETE SET DEFAULT: başvurulan tablonun bir satırı silinirse, referans tablonun tüm eşleşen satırlarındaki tüm referans sütunları sütunun varsayılan değerine ayarlanır.
  • ON DELETE RESTRICT: eğer başvuru satırında eşleşen herhangi bir satır varsa, başvuru satırında bir satır silmek yasaktır.
  • ON DELETE NO ACTION (varsayılan) : referans silme işlemi yok; başvuru kısıtı sadece bir kısıtlama kontrolü belirler.

Yabancı anahtar bağımlı ilişkiyi kurar. <referential action>İlişki çözülür ne olacağını belirler.

Örnek / Metafor / Açıklama

Her yerde: Bu örnek için, biz toplumun ve ekonominin ortak modelini kabul edecek businessbir ilişki sürdürüyor bir şirkettir bourgeoisiebir içinden fatcat_owner.

CREATE TABLE bourgeoisie(
  fatcat_owner varchar(100) PRIMARY KEY
);
INSERT INTO bourgeoisie(fatcat_owner) VALUES
  ( 'Koch Brothers' );

CREATE TABLE business (
  name         varchar(100),
  fatcat_owner varchar(100) REFERENCES bourgeoisie
);
INSERT INTO business(name, fatcat_owner)
  VALUES ('Georgia-Pacific', 'Koch Brothers');

Her şey businesskendilerinden doğrudan etkilenirse bourgeoisie, fatcat_ownero zaman işçi temizliğinden sonra sınıfları temizlemiş fatcat_ownerve sınıfsız bir topluma sahip olduğunuzda ne yaparsınız ?

-- Viva la revolución 
BEGIN;
  DELETE FROM bourgeoisie;
END;

Burada bir kaç seçeneğin var.

  • Devrimi durdur. SQL parlance olarak RESTRICT. Bazı insanlar bunun daha az şeytan olduğuna inanıyor, ama genelde yanılıyorlar.
  • Devam etmesine izin ver. Eğer öyleyse, devrim gerçekleştiğinde SQL size dört seçenek sunar,

    • SET NULL-- boş bırak. Kim bilir, belki kapitalizm yeniden bourgeoisiegündeme gelir ve oligarşiler ruloyu doldurur fatcat_owners. Önemli not, sütun olmalı NULLABLE(olmamalıdır NOT NULL) yoksa bu asla gerçekleşemez.
    • SET DEFAULT- belki bir vardı DEFAULTbu ele o? A DEFAULTbir işlevi çağırabilir. Belki şemanız zaten devrime hazırdır.
    • CASCADE- hasar kontrolü yok. Eğer bourgeoisiegiderse, öyle de olur business. Bir iş varsa gereken bir var fatcat_pig, o zaman bazen veri kaybetmek yerine olmayan bir iş var daha mantıklı businessmasaya.
    • NO ACTION- bu aslında çekimi geciktirme yöntemidir, MySQL'de durumundan farklı değildir RESTRICT, ancak PostgreSQL'de yapabileceksiniz

      -- Not a real revolution.
      -- requires constraint be DEFERRABLE INITIALLY DEFERRED
      BEGIN;
        SET CONSTRAINTS ALL DEFERRED;
        DELETE FROM bourgeoisie;
        INSERT INTO bourgeoisie VALUES ( 'Putin' );
        UPDATE business SET fatcat_pig = 'Putin';
      END;
      

      Böyle bir sistemde, kısıtlama sadece işlemin gerçekleşmesinden önce doğrulanır. Bu, devrimi durdurmaya neden olabilir, ancak işlem sırasında bir miktar "kurtarma" için iyileşme sağlayabilirsiniz.


Does referencedtablo ana tablo anlamına ve referencingmasa alt tablo demektir?
sg552

@ sg552 Evet, doğru anladınız.
informatik01

0

Basit bir hatırlatıcı olur

Ebeveyn CASCADE SİLECEĞİNDE [silerek] burada

Bu size, hangisinin silindiğini (ebeveynin silen) basamaklandırıldığını, ON DELETE CASCADE deyiminin nereye gittiğini (çocukta) ve neyin silindiğini (çocuk) söyler .


-3

Belki sözdizimini rasyonelleştirebiliriz. Bir Python örneği ele alalım:

class Parent(self):
    # define parent's fields

class Child(self):    
    # define child's fields
    parent_pk_is_childs_foreign_key = models.ForeignKey(Parent, on_delete=models.CASCADE)

Bu satırın söylediği, ebeveynin on_delete'sidir (ifadede yanlışlıkla belirtilen), lütfen silme işlemini çocuk üzerine aktarın. CASCADE deyiminin çocuk düzeyinde tanımlanmasının nedeni, silinmesi gereken çocukları işaret ediyor.

Örneğin, başka bir sınıfa sahipseniz

class GrownUpChild(self):    
        # define grown up child's fields
        parent_pk_is_childs_foreign_key = models.ForeignKey(Parent, on_delete=models.DO_NOTHING)

Bu yapı, hangi çocukların hangi çocukların kaldırılması gerektiğini (Çocuk) ve hangi çocukların yetim kalmış olsalar da (GrownUpChild) kalacaklarını açıkça gösterecektir.

[Düzenleme: Tartışma bağlamında, özellikle on_delete = models.CASCADE, vb. Durumlarda], aslında, denetleme ve raporlama nedenlerinden dolayı, kazayla iyileşmenin yanı sıra, silinmiş bir ebeveyni çocuklarını bırakmak genellikle istenen bir davranıştır. silme. [Tabii ki, kurumsal seviye yazılımı bu davranış etrafında oluşturulacak ve silinmiş kayıtları, aslında onları silmek yerine, silinmiş olarak işaretleyecektir ve ön uç için herhangi bir sorguya dahil etmeyecek, ek olarak bazı özel tasarlanmış raporları içerecektir. Buna ek olarak, genellikle kullanıcı arayüzü yöneticisi tarafından yürütülecek olan ve veritabanındaki herhangi bir ilgiden kaçınılacak olan veritabanından silinen == 1 kayıtları temizleme fonksiyonuna sahip olacaktır.]


1
“Aslında, denetleme ve raporlama nedenleriyle kaza sonucu silme durumlarını kurtarma nedeniyle çocuklarını silinmiş bir ebeveyni terk etmek genellikle arzu edilen bir davranıştır” - bu (aklı başında) bir veri tabanında felaket olur.
dezso

@dezso girişiniz için teşekkürler. Bununla birlikte, çoklu işletme düzeyinde CRM sistemleri de aynısını yapar.
George Mogilevsky

Daha mantıklı hale getirmeyen TBH. Bir keresinde böyle bir yaklaşımdan kaynaklanan işleri düzeltmek için bir görev aldım - maaş hariç, neşe yok.
dezso

anlayışlı bir veritabanı yöneticisi gibi konuşuyorsunuz :) Tamamen amacınızı duyabiliyorum. Yukarıda bahsettiğim yazılım, aslında silinenleri kaldırmak için bir işleve sahipti; = 1 bu nedenle bu çağrıyı yapmak için uygulamanın yöneticisine kalmıştır. Normalde veritabanı yöneticisi bu yönü korumaya dahil bile değildir. Ve ayrıca, tüm yazılımın veritabanı sınıfı konsept etrafında inşa edilmiştir, bu yüzden her zaman taşlama işlemlerinde silinen bayrağını kontrol eder
George Mogilevsky

Evet, bu bilinen ve aklı başında bir kalıptır - ancak o zaman bunu yansıtmak için yukarıdaki ifadeleri muhtemelen değiştirmeniz gerekir.
dezso
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.