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

PHP 刪除無限分類與所有子分類:遞歸收集 ID 單次 SQL 刪除

     編輯:PHP 綜合知識

核心邏輯

  1. 取得目標分類 ID
  2. 遞歸收集所有後代分類 ID
  3. 組合成 IN (...) 單次刪除

刪除入口

<?php
$act = isset($_GET['act']) ? trim($_GET['act']) : '';
if ($act === 'del') {
    $sort_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
    if ($sort_id === 0) exit('Invalid ID');

    $ids = $sort_id . getChildrenIds($sort_id); // 字串 "1,2,3,4"

    $sql = "DELETE FROM `article_sort` WHERE `sort_id` IN ($ids)";
    $res = $db->exec($sql); // PDO::exec 返回影響行數

    if ($res !== false) {
        alert('刪除成功', 'sort_list.php');
    } else {
        alert('刪除失敗', 'sort_list.php');
    }
    exit;
}
?>

遞歸收集子分類 ID

<?php
/**
 * 遞歸取得指定分類下所有後代 ID 字串 (如 ",2,3,5")
 *
 * @param int $sort_id 父分類 ID
 * @return string 以逗號開頭的 ID 字串
 */
function getChildrenIds($sort_id)
{
    global $db;
    $ids = '';

    $sql = "SELECT `sort_id` FROM `" . $db->table('article_sort') . "` WHERE `parent_id` = ?";
    $stmt = $db->prepare($sql);
    $stmt->execute([$sort_id]);

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $ids .= ',' . $row['sort_id'];
        $ids .= getChildrenIds($row['sort_id']);
    }

    return $ids;
}
?>

效能與安全優化

問題解決方案
N+1 查詢改用 Closure Table 或 遞歸 CTE (MySQL 8.0+) 單次查詢取得完整子樹
SQL 注入ID 已 intval,IN 子句拼接安全;或改用 WHERE sort_id IN (?,?,...) 參數綁定
超大 ID 字串超過 SQL 長度限制分批刪除或使用臨時表
誤刪保護刪除前檢查文章關聯、權限驗證、軟刪除 (deleted_at)

MySQL 8.0 遞歸 CTE 範例

WITH RECURSIVE `cte` AS (
  SELECT `sort_id` FROM `article_sort` WHERE `sort_id` = ?
  UNION ALL
  SELECT a.`sort_id` FROM `article_sort` a
  JOIN `cte` c ON a.`parent_id` = c.`sort_id`
)
DELETE FROM `article_sort` WHERE `sort_id` IN (SELECT `sort_id` FROM `cte`);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved