mysql - 插入多个多对多关系

标签 mysql rest stored-procedures many-to-many

我有一个典型的多对多关系,涉及 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。希望我可以将它们插入到存储过程中。

问题是我不希望在 productuserproduct_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_idurl 设置为映射表的复合主键,以便应用 ON DUPLICATE KEY UPDATE 子句

ALTER TABLE user_product ADD PRIMARY KEY (user_device_id, product_url);

关于mysql - 插入多个多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24596313/

相关文章:

rest - 用于内部访问的 openshift 主服务器的主机名是什么?

sql - 我们可以在 SQL Server 中使用 while 循环将记录存储在临时表中吗?

java - 使用 spring 框架将重音字符存储到数据库时出现问题

mysql - 使用 Wt::Dbo 导致 MySQL 准备语句泄漏

php - REST API 部分工作 - PHP

mysql - 一个表中的多个计数无意中对行中的列求和

rest - AppNexus API 未返回维度

mysql - 创建存储过程 - MySQL

php - 数据库表未更新

php - 只返回一条记录