2011-12-16 10 views
0

テーブルが自身を再帰的にポイントする特定のレコードIDから子孫レコードを削除する方法はありますか?特に、私はPDO、PHP、およびMySQL 5.0+を使用しています。 MySQL、PHP、およびPDOでの効率的なDescendantレコードの削除

は、これらの列でカテゴリテーブルを想像してみて:

  • ID
  • PARENT_ID
  • カテゴリ名

IDが0の場合、それはルートカテゴリです。そのidはプライマリキーではありません。心配してください。多くのルートカテゴリがあります。

食べ物やシェルターのルートカテゴリ、それらの子、それらの子などのように、いくつかの層が深いと想像してください。これらは子孫です。誰かが「野菜」を削除するとしたら、食べ物とシェルターはルートカテゴリとして残されていると思うかもしれませんが、ビーンズと同様にニンジンはなくなります。マンションとキャビンも別の木から来たので、後に残されます。それを得る?

EDIT:私の悪い - 忘れてしまった列 - 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){} 
} 
2

あなたのシナリオではおそらくオプションではありませんが、階層データを格納するためのネストされたセットモデルは、説明したような操作を非常に効率的にすることができます。

また、この記事は役に立つかもしれません:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

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' 

再帰的に動作するので、第二に「野菜」と第三に「にんじん」と「豆」。

関連する問題