下面是我的(简化)架构(在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;
请告诉我,有一种更好的方式,我没有看到。
答案 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');
否则,您的解决方案非常标准,除非您想使用触发器来维护映射表。