[英]Efficient Descendant Record Deletion in MySQL, PHP, and PDO
從給定記錄ID中刪除后代記錄的策略是什么,在該表中表遞歸地指向其自身? 具體來說,我正在使用PDO,PHP和MySQL 5.0+。
想象一下帶有這些列的類別表:
如果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.