我有一个典型的多对多关系,涉及 3 个表:
用户(ID、姓名)
产品(id、名称、当前价格、图片、网址)
user_product_mapping(user_id、product_id、my_purchase_price)
。
请注意,映射表有一个额外的列my_purchase_price
,因为用户可以指定自己的价格。
我正在构建一个允许批量插入的 API,例如
curl -d '{"products": [\
{"image":"http://example.com/images/testproduct", "name":"testproduct", "url":"http://example.com/products/test", "current_price":50, "my_purchase_price":40},\
{"image":"http://example.com/images/testproduct2","name":"testproduct2","url":"http://example.com/products/test2","current_price":100,"my_purchase_price":80} \
]}' \
-X POST http://example.com/users/1/products -H "Content-Type: application/json"
本例中,用户ID为1,需要插入2个产品,价格分别为50、100,用户指定的价格分别为40、80。
我的问题是:如何有效地将数据插入到 3 个表中(如果不存在则创建用户条目)?我不想插入 1 by 1。希望我可以将它们插入到存储过程中。
问题是我不希望在 product
、user
和 product_user_mapping
表中出现重复项。因此,如果产品表中已经存在此类产品(URL 是唯一键),那么我将只更新它们的价格。如果 product_user_mapping
表中已存在映射,则仅更新 my_purchase_price。我基本上需要 2 个插入(如果不存在)并更新重复项,但是第二个插入更新需要知道第一个插入更新的 ID,并且我找不到在第二次插入期间更新 my_purchase_price
的有效方法/更新。更有趣的是,API 实际上还允许用户指定用户名,这意味着如果用户表中不存在用户 1,我也会在用户表中为用户 1 创建一个条目。
我故意不使用 URL 作为产品表中的主键,因为我认为使用 URL 作为主键通常是一个坏主意(是吗?)。我尝试了多种方法,但没有一个令我满意:
方法一:
通过重复 key (url)插入产品更新价格、图片
- 获取之前插入/更新的产品 ID 的所有 ID。
在重复 key 更新 my_purchase_price 时插入 user_product_mapping
。
方法2:
INSERT INTO product ON DUPLICATE KEY (url) UPDATE price, image;
DELETE FROM user_product_mapping
WHERE user_id=1
AND product_id NOT IN (
SELECT product id
FROM product
WHERE url NOT IN (the urls passed from api)
);
INSERT INTO user_product_mapping;
我似乎已经编写了至少 3 个插入更新语句,并且可能还需要一个游标。我有一种感觉,我可能把事情搞得太复杂了。
最佳答案
如果有人遇到同样的问题,我的解决方案是将 URL 作为产品表中的主键(不确定这是否是一个好主意)。因此,在开始所有插入操作之前,我知道我手头上的所有键。然后,我发出两个重复插入更新查询(请注意,此步骤可以在一个 SQL 语句中完成):
INSERT INTO product (url, name, image, current_price)
VALUES
('http://example.com/product/test', 'testproduct', 'http://example.com/images/testproduct', 10)
ON DUPLICATE KEY UPDATE
url=VALUES(url),
image=VALUES(image),
current_price=VALUES(current_price);
INSERT INTO user_product (user_id, product_url, my_purchase_price)
VALUES
(1, 'http://example.com/products/test', 8)
ON DUPLICATE KEY UPDATE
my_price=VALUES(my_price);
请记住将 user_id
和 url
设置为映射表的复合主键,以便应用 ON DUPLICATE KEY UPDATE
子句
ALTER TABLE user_product ADD PRIMARY KEY (user_device_id, product_url);
关于mysql - 插入多个多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24596313/