【问题标题】:Efficient Descendant Record Deletion in MySQL, PHP, and PDOMySQL、PHP 和 PDO 中的高效后代记录删除
【发布时间】:2012-01-22 08:07:12
【问题描述】:

从表递归指向自身的给定记录 ID 中删除后代记录的策略是什么?具体来说,我使用的是 PDO、PHP 和 MySQL 5.0+。

想象一个包含这些列的类别表:

  • 身份证
  • parent_id
  • 类别名称

如果 ID 为 0,则它是根类别。请注意,该 id 不是主键 - 可以有许多根类别。

想象它有好几层深,例如 Food 和 Shelter 根类别,然后是它们的子类别,以及它们的子节点,等等。这些是后代。例如,如果有人要删除蔬菜,那么您可以预期食物和庇护所将作为根类别留下,但胡萝卜会消失,豆类也会消失。豪宅和小屋也将被留下,因为它们来自另一棵树。明白了吗?

编辑:我的错--忘记了一个列--parent_id。这很关键。

【问题讨论】:

    标签: php mysql sql recursion descendant


    【解决方案1】:

    在您的场景中可能不是选项,但是,用于存储分层数据的嵌套集模型可以使您描述的操作非常有效。

    这篇文章也可能有用:

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

    【讨论】:

      【解决方案2】:

      一个简单的级联参照完整性应该可以做到 - 使用 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'
      

      ...在第一级删除“食物”,在第二级删除“蔬菜”,在第三级删除“胡萝卜”和“豆类”。

      【讨论】:

        【解决方案3】:

        虽然嵌套集合模型更强大,但有时下面的递归示例已经足够了。

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

        【讨论】:

          猜你喜欢
          • 2015-03-12
          • 1970-01-01
          • 2018-06-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-10
          • 2013-04-30
          相关资源
          最近更新 更多