【问题标题】:How to delete tree in parent_id=>id structure如何删除 parent_id=>id 结构中的树
【发布时间】:2013-01-27 22:00:56
【问题描述】:

我有一个使用parent_id=>id 结构映射树的数据库表(目录)。

我有另一个表(文件)将文件映射到第一个表中的项目directory_id => directories.id

我想要做的是,给定第一个表中的 id,删除第二个表中与同一树中所选 id 相同或更高的所有行。

然后删除第一个表中所有在同一棵树中相等或向上的行。

解释它的最好方法是文件系统,删除一个目录,它会删除它下面的所有内容。

我能想到的唯一方法是(半伪代码!):

$id = :id
$files = array();
$directories = array($id);
delete_tree($query:results, $files, $directories);

function delete_tree($id, &$files, &$directories){
    $query = SELECT `id` FROM `directories` WHERE `parent_id` = $id;
    foreach($query:results as $directory){
        $directories[] = $directory:id;
        $query2 = SELECT `id` FROM `files` WHERE `directory_id` = $directory:id;
        foreach($query2:results as $file){
            $files[] = $file:id
        }
        delete_tree($directory:id, $files, $directories);
    }
}

$query = DELETE from `directories` WHERE `id` IN (explode(',', $directories));
$query = DELETE from `files` WHERE `id` IN (explode(',', $files));

【问题讨论】:

    标签: php mysql recursion tree


    【解决方案1】:

    你可以尝试使用递归 sql ;-)

    在这里你可以找到信息:

    http://wiki.yaslaw.info/wikka/MySQLTree

    在“4)..”下,您可以找到所需 sql 条件的示例。

    这里是示例代码:

    SELECT
        nav.id,
        nav.title
    FROM
        (
            SELECT
                @rownum := @rownum+1 AS rownum, 
                IF(@lastid <> mylist.id, @id := mylist.id, @id) AS pathid,
                @lastid := mylist.id AS id,
                @id := (SELECT parentID FROM nav  WHERE id = @id) AS parentID
            FROM
                (SELECT @id := 0, @lastid := 0, @rownum := 0) AS vars,
                (SELECT id FROM nav) AS myloop,
                (SELECT id FROM nav) AS mylist
        ) AS t
        INNER JOIN nav
            ON t.id = nav.id
    WHERE
        pathid = 2  // all subitems from id=2
    

    【讨论】:

      【解决方案2】:

      我会通过数据库限制来做到这一点。

      假设我有以下表格

      我可以定义这两种关系,以便通过删除主记录来级联删除记录。

      phpMyAdmin 中的示例:

      //目录

      //文件

      现在我删除 id=10 的目录“03”

      //目录

      //文件

      如您所见,两个表中作为节点子节点的所有记录都已删除。非常快速,无需任何脚本。

      这是一个小转储:

      CREATE TABLE IF NOT EXISTS `directories` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `name` varchar(20) NOT NULL,
        `parent_id` int(11) NOT NULL,
        PRIMARY KEY (`id`),
        KEY `parent_id` (`parent_id`)
      ) ENGINE=InnoDB  DEFAULT CHARSET=cp1250 AUTO_INCREMENT=13 ;
      
      INSERT INTO `directories` (`id`, `name`, `parent_id`) VALUES (0, 'root', 0),(6, '02', 0), (10, '03', 0),(11, '031', 10),(12, '032', 10);
      
      CREATE TABLE IF NOT EXISTS `files` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `name` varchar(20) NOT NULL,
        `directory_id` int(11) NOT NULL,
        PRIMARY KEY (`id`),
        KEY `directory_id` (`directory_id`)
      ) ENGINE=InnoDB  DEFAULT CHARSET=cp1250 AUTO_INCREMENT=7 ;
      
      
      INSERT INTO `files` (`id`, `name`, `directory_id`) VALUES (2, '031_f01', 11),(3, '031_f02', 11),(4, '02_f01', 6),(6, '02_f02', 6);
      
      
      ALTER TABLE `directories`
        ADD CONSTRAINT `directories_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `directories` (`id`) ON DELETE CASCADE;
      
      ALTER TABLE `files`
        ADD CONSTRAINT `files_ibfk_1` FOREIGN KEY (`directory_id`) REFERENCES `directories` (`id`) ON DELETE CASCADE;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-06
        • 1970-01-01
        • 1970-01-01
        • 2012-03-05
        • 2014-03-27
        • 2021-11-18
        相关资源
        最近更新 更多