更新MySQL中的关联表

时间:2008-11-14 04:09:45

标签: sql mysql database

下面是我的(简化)架构(在MySQL版本5.0.51b中)和我更新它的策略。必须有一个更好的方法。插入新项目需要4次访问数据库,编辑/更新项目需要 7

项目:itemId,itemName
类别:catId,catName
地图:mapId *,itemId,catId
* mapId(varchar)是itemId + |的concat + catId

1)如果插入:插入项目。通过MySQL API获取itemId。
其他更新:只需更新项目表。我们已经有了itemId。

2)有条件地批量插入categories

INSERT IGNORE INTO categories (catName)
VALUES ('each'), ('category'), ('name');

3)从categories中选择ID。

SELECT catId FROM categories
WHERE catName = 'each' OR catName = 'category' OR catName = 'name';

4)有条件地批量插入map

INSERT IGNORE INTO map (mapId, itemId, catId)
VALUES ('1|1', 1, 1), ('1|2', 1, 2), ('1|3', 1, 3);

如果插入:我们已经完成了。其他更新:继续。

5)我们可能不再将类别与我们在更新之前所做的项目相关联。删除此itemId的旧类别。

DELETE FROM MAP WHERE itemId = 2
AND catID <> 2 AND catID <> 3 AND catID <> 5;

6)如果我们将自己与一个类别脱离关系,那么我们就有可能让它成为孤儿。我们不希望类别没有项目。因此,如果affected rows > 0,则杀死孤儿类别。我还没有找到在MySQL中结合这些的方法,所以这是#6&amp; #7。

SELECT categories.catId
FROM categories
LEFT JOIN map USING (catId)
GROUP BY categories.catId
HAVING COUNT(map.catId) < 1;

7)删除在步骤6中找到的ID。

DELETE FROM categories
WHERE catId = 9
  AND catId = 10;

请告诉我,有一种更好的方式,我没有看到。

3 个答案:

答案 0 :(得分:2)

您可以采取一些措施来简化:

  • 了解[INSERT...ON DUPLICATE KEY UPDATE] [1]

  • 在插入新类别之前删除旧类别。这可能会从指数中获益更多。

    DELETE FROM map WHERE itemId=2;

  • 您可能不需要map.mapID。相反,在(itemID, catID)上声明复合主键。

  • 正如彼得在答案中所说,使用MySQL的多表删除:

    DELETE categories.* FROM categories LEFT JOIN map USING (catId) 
    WHERE map.catID IS NULL
    

    http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

答案 1 :(得分:2)

此外,如果您担心前往数据库,请执行存储过程。然后你有一次旅行。

答案 2 :(得分:1)

步骤6&amp; 7可以轻松组合:

DELETE categories.*
FROM categories
LEFT JOIN map USING (catId)
WHERE map.catID IS NULL;

步骤3&amp; 4也可以合并:

INSERT IGNORE INTO map (mapId, itemId, catId)
    SELECT CONCAT('1|', c.catId), 1, c.catID
    FROM categories AS c
    WHERE c.catName IN('each','category','name');

否则,您的解决方案非常标准,除非您想使用触发器来维护映射表。