MySQL在多个表上批量插入

问题描述 投票:0回答:2

我有一个带有2个表productsproduct_variants的MySQL数据库。产品具有许多产品变型。这里是一个示例:

products
+----+------+
| id | name |
+----+------+
|  1 | Foo  |
|  2 | Bar  |
+----+------+

product_variants
+----+-------------+--------+
| id | product_id  | value  |
+----+-------------+--------+
| 10 |           1 | red    |
| 11 |           1 | green  |
| 12 |           1 | blue   |
| 13 |           2 | red    |
| 14 |           2 | yellow |
+----+-------------+--------+

现在,我需要以最有效,最快的方式批量插入许多带有其变体的产品。我有许多产品(100k +)的JSON,如下所示:

[
  {
    "name": "Foo",
    "variants": [{ "value": "red" }, { "value": "green" }, { "value": "blue" }]
  },
  {
    "name": "Bar",
    "variants": [{ "value": "red" }, { "value": "yellow" }]
  },
  ...
]

我应该从中生成查询以插入产品。

我的想法是像这样使用insert查询:

INSERT INTO `products` (name) VALUES ("foo"), ("bar"), ...;

但是我不知道在product_id的插入查询中要使用什么product_variants(外键):

INSERT INTO `product_variants` (product_id,value) VALUES (?,"red"), (?,"green"), ...;

(这些交易内的查询)

我曾考虑以手动方式从上一个ID增量指定产品ID,但是当并发连接同时插入产品或同时运行2个或多个批量插入过程时,会出现错误。

我可以使用什么策略来实现自己的目标?有没有标准的方法可以做到这一点?

ps:如果可能,我不想更改2个表的结构。

mysql sql performance bulkinsert
2个回答
1
投票

您可以使用last_insert_id()从最后一条语句中获取最后生成的ID。但是,如上所述,由于这仅获得语句的最后一个ID,因此要求您分别处理每个产品。您可以批量插入变体。但是从给定JSON的结构来看,我认为这使得遍历该JSON变得更加容易。应将每个产品及其变体插入事务中,以便如果由于某种原因导致产品表中的INSERT失败,则不会将产品的变体添加到先前的产品中。

START TRANSACTION;
INSERT INTO products
            (name)
            VALUES ('Foo');
INSERT INTO product_variants
            (product_id,
             value)
            VALUES (last_insert_id(),
                    'red'),
                   (last_insert_id(),
                    'green'),
                   (last_insert_id(),
                    'blue');
COMMIT;

START TRANSACTION;
INSERT INTO products
            (name)
            VALUES ('Bar');
INSERT INTO product_variants
            (product_id,
             value)
            VALUES (last_insert_id(),
                    'red'),
                   (last_insert_id(),
                    'yellow');
COMMIT;

db<>fiddle


0
投票

如果您已经在表中包含JSON,则可以使用两个语句来完成(非常有效):

INSERT INTO Products (name)
    SELECT name
        FROM origial_table;  -- to get the product names

INSERT INTO Variants (product_id, `value`)
    SELECT  ( SELECT id FROM Products WHERE name = ot.name ),
            `value`
        FROM origial_table AS ot;

实际上,namevalue需要适合作为JSON表达式以提取值。

© www.soinside.com 2019 - 2024. All rights reserved.