1

我有下表:

CREATE TABLE `products_quantity` (
  `id` int(11) NOT NULL auto_increment,
  `product_id` varchar(100) NOT NULL,
  `stock_id` int(11) NOT NULL,
  `quantity` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `product_id` (`product_id`,`stock_id`),
  KEY `products_quantity_product_id` (`product_id`),
  KEY `products_quantity_stock_id` (`stock_id`)
) ENGINE=MyISAM

product_id 是另一个表的外键,stock_id 也是。

该表目前有 10 000 多行,所有行都具有相同的 stock_id (1)。我想要做的是将其所有行复制两次,两次都使用新的 stock_id(2 和 3),以及“数量”的随机值。

这是SQL:

INSERT INTO `products_quantity` (product_id, stock_id, quantity)
    SELECT product_id, 2 AS stock_id, FLOOR(-1 + (RAND() * 15)) AS random_quantity FROM products_quantity;

这很好用。它使用另一个 stock_id 创建 10 000 多个新行,因此尽管每行的 product_id 已经存在,但不会违反唯一性约束。

此时表中的行示例,按 product_id 排序(一个 VARCHAR,丑陋但必要),请原谅格式:

22      0032705090062   1   1
10783   0032705090062   2   13
21      0032705090345   1   6
10784   0032705090345   2   0
...

这是每个 product_id 两次,每个 stock_id 一次。现在,如果我想以类似的方式创建第三只股票,使用与上次完全相同的查询但替换为“3 AS stock_id”,我会在第一个产品行中收到此错误:

“密钥 2 的重复条目 '0032705090062-3'”

虽然 product_id 0032705090062 和 stock_id 3 的组合与 stock_id 1 和 2 的组合一样唯一,但据说突然违反了唯一性约束,不是吗?

有趣的是,创建了单行,所以有一个新行:

21563    0032705090062  3   5

...但这是我试图插入的 10 000 多个中唯一的一个。

我在这里想念什么?为什么第一个 SELECT...INSERT INTO 有效,而第二个无效?

4

2 回答 2

2

您从要插入的同一张表中进行选择,所以第一次抓取

22      0032705090062   1       1
21      0032705090345   1       6

然后插入

10783   0032705090062   2       13
10784   0032705090345   2       0

但是,当您再次运行它时,它将:

GET     22      0032705090062   1       1
INSERT  21563   0032705090062   3       5
GET     10783   0032705090062   2       13
INSERT          0032705090062   3   <-- oops, already exists

您只需要添加WHERE stock_id = 1到您的 SELECT

于 2009-05-22T09:28:55.537 回答
1

简单的:

INSERT INTO `products_quantity` (product_id, stock_id, quantity)
    SELECT 
      product_id, 
      3 AS stock_id, 
      FLOOR(-1 + (RAND() * 15)) AS random_quantity 
    FROM 
      products_quantity;
    WHERE
      stock_id = 1  /* !!!!! */

您的第二次插入失败,因为现在有 20.000 行(不是 10.000,就像您想的那样)。添加 where 子句可确保仅插入 10.000。

于 2009-05-22T09:30:48.323 回答