首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 遞迴刪除樹狀資料:部門/分類多層級刪除完整範例

     編輯:PHP 相關知識

針對「刪除節點及其所有子孫節點」的經典需求,提供以 parent_id 關聯的遞迴刪除實作,並說明效能優化與替代方案。

資料表結構

CREATE TABLE dept (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    parent_id INT DEFAULT 0,  -- 0 為根節點
    INDEX idx_parent (parent_id)
);

遞迴刪除實作 (PDO)

<?php
function deleteDeptTree(PDO $pdo, int $deptId): bool {
    // 1. 找直系子節點
    $stmt = $pdo->prepare('SELECT id FROM dept WHERE parent_id = ?');
    $stmt->execute([$deptId]);
    $children = $stmt->fetchAll(PDO::FETCH_COLUMN);

    // 2. 遞迴刪除子樹
    foreach ($children as $childId) {
        deleteDeptTree($pdo, $childId);
    }

    // 3. 刪除自己
    $del = $pdo->prepare('DELETE FROM dept WHERE id = ?');
    return $del->execute([$deptId]);
}

// 使用
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
deleteDeptTree($pdo, 5); // 刪除 id=5 及其所有下層
?>

效能隱憂與優化方案

  • N+1 查詢:每層各查一次,深層樹會產生大量查詢。
  • 解法 A:CTE 遞迴查詢 (MySQL 8.0+ / PostgreSQL)
    WITH RECURSIVE to_delete AS (
        SELECT id FROM dept WHERE id = 5
        UNION ALL
        SELECT d.id FROM dept d JOIN to_delete td ON d.parent_id = td.id
    )
    DELETE FROM dept WHERE id IN (SELECT id FROM to_delete);
  • 解法 B:Closure Table / 路徑枚舉:額外儲存祖先路徑 path = '1/5/12/',刪除變成 DELETE WHERE path LIKE '1/5/12/%',單查詢完成。
  • 解法 C:應用層收集 ID 再批次刪除:先 BFS/DFS 收集所有 ID,最後 DELETE WHERE id IN (...)。

應用層收集 ID 範例 (避免深層遞迴爆堆疊)

<?php
function collectSubtreeIds(PDO $pdo, int $rootId): array {
    $ids = [];
    $stack = [$rootId];
    while ($stack) {
        $id = array_pop($stack);
        $ids[] = $id;
        $stmt = $pdo->prepare('SELECT id FROM dept WHERE parent_id = ?');
        $stmt->execute([$id]);
        $stack = array_merge($stack, $stmt->fetchAll(PDO::FETCH_COLUMN));
    }
    return $ids;
}

$ids = collectSubtreeIds($pdo, 5);
$pdo->exec('DELETE FROM dept WHERE id IN (' . implode(',', $ids) . ')');
?>

總結

教學/小資料量用遞迴函式最直觀;生產環境大樹狀結構請改用 CTE、Closure Table 或批次刪除,避免效能與堆疊溢位風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved