2012-09-17 28 views
1

如何在父表中刪除記錄時在子表中設置parent_id = NULL?如何在父表中刪除記錄時在子表中設置parent_id = NULL?

這就像在MySQL的INNODB表中的ON DELETE = SET NULL,但我想避免在INNODB級別使用所有這些(級聯,忽略,更新和設置null)功能,並將其移動到atk4模型,以保持所有這一切邏輯一個地方。

例如,

class Model_Parent extends Model_Table{ 
    public $table='parent'; 
    function init(){ 
    parent::init(); 
    $this->addField('name'); 
    $this->hasMany('Child'); 
    $this->addHook('beforeDelete',$this); 
    } 
    function beforeDelete($m){ 
    // I guess here I should somehow set parent_id=NULL in all related Model_Child 
    // records, but when I do so, then it's again DB constraint violation of course 
    $c = $m->ref('Child'); 
    foreach($c as $junk){ 
     $c->set('parent_id',NULL); // this and below is not working 
     $c->save(); 
    } 
    } 
} 

class Model_Child extends Model_Table{ 
    public $table='child'; 
    function init(){ 
    parent::init(); 
    $this->addField('name'); 
    $this->hasOne('Parent'); 
    } 
} 

回答

1

這很簡單,你只需要進入DSQL從型號:

$m->ref('Child')->dsql()->set('parent_id',null)->update(); 

更多信息:http://www.youtube.com/watch?v=sSRaYpoJFHk&list=PL7CBF92AB03A1CA3B&index=3&feature=plpp_video

+0

這按預期工作。 奇怪的是它看起來和我之前做的一樣(用foreach循環和save()方法),但是這個工作並且save()不用。 無論如何,這是真正回答上面問題的帖子,所以我會接受它。上面的其他帖子和評論也很有用 - 請檢查一下。 – DarkSide

+0

您的解決方案將單獨加載每個條目,這將非常有效地利用SQL。 dsql()的使用速度要快得多。我可以問你在你自己的例子中嘗試這個:$ c-> set('parent_id',$ c-> dsql() - > expr('null'));', - 我只是好奇它是否會修理它。 – romaninsh

+0

「null」的錯誤現在已修復,您可以再次編寫'$ c-> set('parent_id',null);'。 – romaninsh

0

檢查PARENT_ID列允許NULL值。

+0

是它.... – DarkSide

1

您試圖通過在代碼中執行典型的數據庫任務來重新發明輪子。

如果您不希望數據庫管理外鍵關係,則不應使用這些關係。在這種情況下,您可以將列設置爲NULL或任何其他值。但沒有人能證明你的數據庫的一致性。

+0

也許你是對的,但什麼是快把我逼瘋了當你在更大的項目中說50或甚至更多的表時,所有這些在刪除和更新設置上都設置爲數據庫級別時,則很難從數據庫管理面板和ATK4模型中一次又一次來回切換。 如果所有這些邏輯分成兩個地方 - 數據庫級別和ATK4模型,則很容易出錯。 – DarkSide

+2

我不小心刪除了一些數據庫塊,尤其是當我將「join」與「leftJoin」混在一起時。級聯刪除是危險的。 – romaninsh

+0

我只能同意你關於級聯刪除。我想我應該在我的項目中嘗試使用軟刪除功能(至少在未來的版本中)。 – DarkSide

相關問題