从许多表中删除数据的正确方法是什么?

时间:2011-10-26 09:59:20

标签: php mysql sql database

如果要删除类别,它将首先删除具有相关组和属性的所有相关产品。产品有很多关系。

这是删除类别时的处理方式:

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行数据(字段已编入索引)。

5 个答案:

答案 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本身不支持它。