如果要删除类别,它将首先删除具有相关组和属性的所有相关产品。产品有很多关系。
这是删除类别时的处理方式:
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行数据(字段已编入索引)。
答案 0 :(得分:3)
如果这些表与foreign key相关,您可以在外键中指定ON DELETE CASCADE
,然后删除类别。你必须切换到InnoDB才能应用它。引用外键上的documentation:
对于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;
使用此外键,每当您在DELETE
上发出categories
语句时,RDBMS也会删除引用此类别的products
。
答案 1 :(得分:2)
由于您使用的是MyISAM且无法进行级联删除,因此您只需执行联合删除即可。
DELETE table1, table2 FROM table1 LEFT JOIN table2 ON table1.id = table2.t1_id WHERE table1.id = $id
答案 2 :(得分:1)
我认为在这里工作的最佳方式是使用支持外键约束的存储引擎(如InnoDB)并让它通过ON DELETE CASCADE处理,以便DBMS为您完成工作。
到目前为止,MyISAM确实not support foreign keys。答案 3 :(得分:1)
如果您不想或不能将数据库引擎更改为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
如果有办法连接要从中删除行的所有表,则可以调整代码以执行这样的单个查询。
答案 4 :(得分:0)
答案已经被接受了,但感兴趣的是:如果你被困在没有进行级联删除的数据库上,你可以使用ORM,例如Propel。我相信可以配置为手动进行级联删除,而db本身不支持它。