当您想要删除一个类别时-它将首先删除所有具有相关组和属性的相关产品。一个产品有许多关系。
当删除一个类别时,它是这样处理的:
if (isset($_POST['catid']) && $_POST['catid'] > 0) {
$category_id = mysql_real_escape_string($_POST['catid']);
$SQL = "SELECT * FROM products WHERE category_id = '$category_id'";
$q_item = mysql_query($SQL);
while ($dItem = mysql_fetch_assoc($q_item)) {
$itemid = $dItem['id'];
$SQL = "SELECT * FROM option_groups WHERE item_id = " . $itemid;
$q = mysql_query($SQL);
while ($option_group = mysql_fetch_assoc($q)) {
$optionGroup = $option_group['id'];
$SQL = "SELECT * FROM options WHERE option_group_id = " . $optionGroup;
$q = mysql_query($SQL);
while ($row = mysql_fetch_assoc($q)) {
$option = $row['id'];
mysql_query("DELETE FROM options WHERE id = " . $option);
mysql_query("DELETE FROM e_groups_options WHERE option_id = " . $option);
}
mysql_query("DELETE FROM option_groups WHERE item_id = " . $itemid);
mysql_query("DELETE FROM products WHERE id = " . $itemid);
}
}
$SQL = "DELETE FROM categories WHERE id = '$category_id'";
mysql_query($SQL);
}
你可以看到,我已经使用了包括许多DELETE查询和代码看起来有点乱,有没有替代的方式和更安全?
存储引擎是MyISAM,我在表中有超过100,000行数据(字段被索引)。
如果这些表与外键相关,则可以在外键中指定ON DELETE CASCADE
,然后删除Category。您必须切换到InnoDB才能应用此功能。引用外键的文档:
对于非InnoDB的存储引擎,MySQL Server解析CREATE TABLE语句中的FOREIGN KEY语法,但不使用或存储它
考虑到级联动作不会触发触发器。
你可以用ALTER TABLE table_name ENGINE = InnoDB
把你的表切换到InnoDB。您可以使用ALTER TABLE
语句添加外键,例如:
ALTER TABLE products
ADD FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE;
使用这个外键,每当您在categories
上发出DELETE
语句时,RDBMS也将删除引用该类别的products
。
由于您使用的是MyISAM,无法执行级联删除,因此您可以简单地执行连接删除。
DELETE table1, table2 FROM table1 LEFT JOIN table2 ON table1.id = table2.t1_id WHERE table1.id = $id
我认为最好的工作方式是使用一个支持外键约束的存储引擎(如InnoDB),并让它通过ON DELETE CASCADE来处理这个问题,这样DBMS就会为你做这项工作。
MyISAM目前还不支持外键
如果您不想或不能将数据库引擎更改为innodb,您可以使用join对多个表进行删除:
DELETE t1, t2, t3
FROM tabel1 AS t1
LEFT JOIN table2 AS t2 ON t1.id = t2.pid
LEFT JOIN table3 AS t3 ON t2.id = t3.pid
WHERE t1.id = $id
如果有一种方法可以连接所有想要从中删除行的表,则可以调整代码以执行这样的单个查询。
一个答案已经被接受了,但出于兴趣:如果您被卡在一个不进行级联删除的数据库上,您可以使用像Propel这样的ORM。我相信,可以配置为手动级联删除,它是不支持的db本地。