簡體   English   中英

MySQL,PHP和PDO中的高效后代記錄刪除

[英]Efficient Descendant Record Deletion in MySQL, PHP, and PDO

從給定記錄ID中刪除后代記錄的策略是什么,在該表中表遞歸地指向其自身? 具體來說,我正在使用PDO,PHP和MySQL 5.0+。

想象一下帶有這些列的類別表:

  • ID
  • parent_id
  • 分類名稱

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

想象一下它的深度是幾層,例如食物和住房根目錄類別,然后是這些類別的子代,等等。 這些是后代。 例如,如果有人要刪除蔬菜,那么您可以期望食物和住房作為根目錄類別會被留下,但是胡蘿卜和豆類都會消失。 豪宅和小屋也將被遺棄,因為它們來自另一棵樹。 得到它?

編輯 :我不好-忘記了一列-parent_id。 這很關鍵。

但是,在您的方案中,可能不是選項,用於存儲分層數據的嵌套集模型可以使您所描述的操作非常有效。

此外,本文可能會有用:

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

一個簡單的級聯引用完整性應該做到這一點-用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'

...在第一級刪除“食物”,在第二級刪除“蔬菜”,在第三級刪除“胡蘿卜”和“豆”。

盡管嵌套集模型更強大,但有時以下帶有遞歸的示例可能就足夠了。

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){}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM