2011-12-16 54 views
0

從給定記錄ID中刪除後代記錄的策略是什麼?具體來說,我使用的是PDO,PHP和MySQL 5.0+。刪除MySQL,PHP和PDO中的高效後裔記錄

想象一個類別表與這些列:

  • ID
  • PARENT_ID
  • CATEGORY_NAME

如果ID爲0,則這是一個根類別。該ID不是主鍵,請注意 - 可以有許多根類別。

想象它有幾層深,就像食物和住房根類別,然後是那些孩子,還有那些孩子,等等。這些是後代。如果有人說要刪除蔬菜,那麼你可能會認爲食品和住房將被留下作爲根類別,但胡蘿蔔將會像豆類一樣消失。大廈和小屋也將被留下,因爲它們來自另一棵樹。得到它?

編輯:我的不好 - 忘了一欄 - parent_id。這非常關鍵。

回答

0

雖然嵌套集模型是更強大的,有時與遞歸下面的例子可能是不夠好。

public function deleteCategory($sCatID) { 
    if (empty($sCatID)) { 
    return FALSE; 
    } 
    // you can get your PDO database connection your own way -- this is my way for my framework 
    $PDO = $this->data->mysql(); 
    // recursively find all the descendents of this category and delete those too 
    $sSQL = " 
    SELECT 
    `id` 
    FROM 
    `categories` 
    WHERE 
    `parent_id` = :parent_id; 
    "; 
    $st = $PDO->prepare($sSQL); 
    $st->bindValue(':parent_id',$sCatID); 
    try { 
    $st->execute(); 
    $rsRows = $st->fetchAll(); 
    foreach($rsRows as $rwRow) { 
     $sChildCatID = $rwRow['id']; 
     // note the recursion here! 
     $this->deleteCategory($sChildCatID); 
    } 
    } catch (PDOException $e) {} 
    unset($st); 
    // now delete this category 
    $sSQL = " 
    DELETE FROM 
    `categories` 
    WHERE 
    `id` = :id 
    LIMIT 1; 
    "; 
    $st = $PDO->prepare($sSQL); 
    $st->bindValue(':id',$sCatID); 
    try { 
    $st->execute(); 
    } catch (PDOException $e){} 
} 
1

一個簡單的級聯參照完整性應該這樣做 - 用ON DELETE CASCADE聲明你的FOREIGN KEY。如果你索引parent_id,它應該甚至是相當有效的(這似乎在MySQL中是必需的;其他DBMS通常允許無索引FK)。

例如:

CREATE TABLE your_table (
    id int PRIMARY KEY, 
    parent_id int DEFAULT NULL, 
    category_name varchar(45) NOT NULL, 
    -- Will also create index on parent_id: 
    CONSTRAINT your_table_fk1 FOREIGN KEY (parent_id) REFERENCES your_table (id) 
     ON DELETE CASCADE 
); 

INSERT INTO your_table (id, category_name) VALUES (1, 'Food'); 
INSERT INTO your_table (id, category_name) VALUES (2, 'Shelter'); 
INSERT INTO your_table (id, parent_id, category_name) VALUES (3, 1, 'Vegetables'); 
INSERT INTO your_table (id, parent_id, category_name) VALUES (4, 3, 'Carrots'); 
INSERT INTO your_table (id, parent_id, category_name) VALUES (5, 3, 'Beans'); 
INSERT INTO your_table (id, parent_id, category_name) VALUES (7, 2, 'Mansions'); 
INSERT INTO your_table (id, parent_id, category_name) VALUES (8, 2, 'Cabins'); 

然後,當你執行...

DELETE FROM your_table WHERE category_name = 'Vegetables' 

...不僅 '蔬菜',而且 '胡蘿蔔' 和 '豆' 將被刪除。

這甚至遞歸工作,所以......

DELETE FROM your_table WHERE category_name = 'Food' 

...刪除「食品」在第一級,「蔬菜」在第二和「胡蘿蔔」和「豆」在第三。