Php 从表中删除嵌套类别
我有一个名为Php 从表中删除嵌套类别,php,mysql,Php,Mysql,我有一个名为categories的表,看起来像这样 +-------------+--------------+---------------+ | id | catName | parentId | +-------------+--------------+---------------+ | 1 | Category 1 | 0 | | 2 | Category 2 | 0
categories
的表,看起来像这样
+-------------+--------------+---------------+
| id | catName | parentId |
+-------------+--------------+---------------+
| 1 | Category 1 | 0 |
| 2 | Category 2 | 0 |
| 3 | Sub Cat 1 | 1 |
| 4 | Sub Cat 2 | 1 |
| 5 | Sub sub cat 1| 4 |
| 6 | Sub sub cat 2| 4 |
| 7 | Category 2 | 0 |
+-------------+--------------+---------------+
删除类别及其直接子级很容易:
mysql_query("DELETE FROM `categories` WHERE `id`='$id'");
mysql_query("DELETE FROM `categories` WHERE `parentId`='$id'");
但是,我需要能够删除一个类别的所有子项。例如,如果类别1
被删除子类别1
,子类别2
,子类别1
,子类别2
将被删除
感谢您的帮助。您可以使用,这是mysql非常好的功能。这是一种用于引用不同关系的完整性检查。例如,如果创建外键,mysql将确保引用的条目存在。在创建外键的过程中,您可以定义如果删除了“父元素”,mysql应该做什么。您可以指定“设置空”、“更新”或“删除级联”。这意味着,如果删除一个类别,则每个连接的子类别也将被删除。由于每个子类别都是子类别的父类别,因此这些子类别也会被删除。为了清晰起见,引用了我的原始答案 更新1:表拆分的问题是不清楚是否有固定数量的子、子、类别。为了实现这一点,您需要将表拆分为尽可能多的子类别,每个子类别都有返回到其父ID的外键。如果子(或子)类别的数量是动态的,则不实用 在这种情况下,我认为你改变自己的想法会有好处 桌子设计。如果将两个表拆分为类别和 可以利用外键的子类别 Straubery描述的功能。例如(这些不是 看起来像表格,但希望这是有意义的)括号里的东西 解释如下: 类别
- id(主键)
- 猫名
- 子单元id(主键)
- id(引用类别表主键的外键)
- 子目录名
DELETE FROM categories
WHERE id IN (1,3,4,5,6);
本论坛帖子中的代码也可以帮助您在php中递归地执行此操作:
我知道这不是一个简洁明了的答案,但也许这将为您指明正确的方向。mysql“删除时级联”功能的演示。如果您在控制台中运行此命令,那么您可以一次运行所有查询,并且输出将有意义。如果您在某个图形工具中运行它,那么我想您必须逐个运行查询
CREATE DATABASE `recursivedemo`;
USE `recursivedemo`;
CREATE TABLE `categories` (
`id` INT AUTO_INCREMENT,
`catName` VARCHAR(50),
`parentId` INT,
PRIMARY KEY (`id`),
KEY `parentId` (`parentId`),
CONSTRAINT `categories_fk_self` FOREIGN KEY (`parentId`) REFERENCES `categories`(`id`) ON DELETE CASCADE
) Engine=InnoDB;
SELECT * FROM `categories`;
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Category 1', NULL);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Category 2', NULL);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Sub Cat 1.1', 1);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Sub Cat 1.2', 1);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Sub sub cat 1.2.1', 4);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Sub sub cat 1.2.2', 4);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Sub Cat 2.1', 2);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Sub Cat 2.2', 2);
INSERT INTO `categories`(`catName`, `parentId`) VALUES('Category 3', NULL);
SELECT * FROM `categories`;
DELETE FROM `categories` WHERE `id`=1;
SELECT * FROM `categories`;
DROP DATABASE `recursivedemo`;
下面是一个简单的递归脚本,用于删除类别和嵌套在其中的所有嵌套类别
try {
$db = new PDO(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
}catch( PDOException $e ) {
echo $e->getMessage();
}
class Category {
function delete_category($parrent){
global $db;
$stmt = $db->prepare("SELECT `id` FROM `categories` WHERE `parrentId`=:parrentId");
$stmt->execute(array('parrentId'=>$parrent));
while($category = $stmt->fetchObject('Category')){
$category->delete_category($category->id);
}
$stmt = $db->prepare("DELETE FROM `category` WHERE `id` = :id");
$stmt->execute(array('id'=>$parrent));
}
function __construct(array $data = NULL) {
if( empty($data) )
return;
foreach( $data as $field => $value ) {
$this->$field = $value;
}
}}
其中$db是用于连接数据库的PDO对象。它可能有一些错误,因为我刚刚修改了我的,以适应您的问题。希望这有帮助
PS:要调用函数,只需执行以下操作:$category=newcategory();
$category->delete\u category($\u GET['id'])
您可以在模型中为已删除的嵌套类别使用以下函数:
public function delete_by_id($cat_id)
{
$this->db->delete('Categories', ['cat_id' => $cat_id]);
$q = $this->db->where('parent_id', $cat_id)->get('Categories');
foreach( $q->result() as $Child ) {
$this->delete_by_id($Child->cat_id);
}
}
请你详细说明一下好吗?谢谢!只需要想想如何使用创建外键:)你可以使用phpMyAdmin或者看看这个网站:我正在使用phpMyAdmin,我刚刚将引擎从MyISAM切换到innoDB,但我仍然找不到选项??:我们找到了!我会让您知道我在现阶段无法更改桌子设计的原因:(还有其他选项吗?可能是代码?上面更新了答案,但我在手机上,所以格式和语法可能不确定。使用前请仔细检查。上面的编辑还假设id是唯一的,因此给定类别的parentid是唯一的。hmmmm我收到此错误
您无法指定从claus更新的目标表“categories”e
@Lee Price是的,我明白了。MySQL不会让你在删除查询的同一个表上执行子查询。我会更新我的答案。再检查一件事。我知道这会删除类别1和子类别1.1,但我不知道它如何删除子类别1.2.1和子类别1.2.2。也许你犯了我第一次阅读时犯的同样错误问题?:)删除parentId连接到顶级类别的第一个级别是一回事,但要删除到第一个子类别下未链接到parentId 1的较低级别是一个更难的问题。也许我在你的答案中遗漏了什么?@Carvelfenton是的,你遗漏了“如果您在控制台中运行此命令,则可以运行所有命令
public function delete_by_id($cat_id)
{
$this->db->delete('Categories', ['cat_id' => $cat_id]);
$q = $this->db->where('parent_id', $cat_id)->get('Categories');
foreach( $q->result() as $Child ) {
$this->delete_by_id($Child->cat_id);
}
}