3

我试图插入/更新的我的 SQL 表有这个定义:

CREATE TABLE `place`.`a_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`some_id` bigint(20) NOT NULL,
`someOther_id` bigint(20) NOT NULL,
`some_value` text,
`re_id` bigint(20) NOT NULL DEFAULT '0',
`up_id` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `some_id_key` (`some_id`),
KEY `some_id_index1` (`some_id`,`someOther_id`),
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;

如您所见, some_id 和 someOther_id 共享一个索引。

我正在尝试执行我的插入/更新语句,如下所示:

INSERT INTO `a_table` (`re_id`,`some_id`,`someOther_id`,`up_id`,`some_value`) VALUES      
(100,181,7,101,'stuff in the memo wow') On DUPLICATE KEY UPDATE 
`up_id`=101,`some_value`='sampleValues'

我希望因为我没有指定 id,所以它将回退到索引键 (some_id_index1) 作为插入/更新规则。但是,它只是插入。

显然这是不正确的。我在这里做错了什么?

4

3 回答 3

7

好的,首先帮助您提出更好的问题。对您的问题“我在这里做错了什么?”的字面回答 没什么。

您有一个具有自动增量主键和两个非唯一二级索引的表。您在没有指定主键值的情况下向该表插入行,因此 MySQL 将使用自动增量规则为其提供唯一键,因此该ON DUPLICATE KEY条件永远不会触发。事实上,有人可能会说这是多余的。

所以你必须问自己的问题是你认为应该发生什么。现在 Stack Overflow 不是一个论坛,所以不要回来为这个问题添加评论,试图澄清你原来的问题。而是制定一个新问题,让那些试图准确回答你所问问题的人清楚。

在我看来,有很多可能性:

  1. 您希望将二级索引修改为唯一。你这样做会触发ON DUPLICATE KEY规则并切换到更新
  2. 您实际上根本不想要自动增量列,some_id实际上应该是您的主键
  3. 您不了解数据库索引的工作原理(特别是可能不需要至少一个二级索引,因为数据库通常可以组合多个索引或使用部分索引来优化您的查询,因此第二个二级索引更有用只有someOther_id字段的索引,除非您正在强制执行特定的唯一性约束。因此,例如,如果您期望多行具有相同但对于任何特定some_id的特定行只有一行,则需要第二个二级索引,但是在这种情况下第一个不会,因为数据库可以使用第二个作为部分索引来实现相同的性能优化)someOther_idsome_id

我建议你坐下来,用笔和纸远离你的电脑,试着准确地写下你想做的事情,这样[选择一个:你的祖母;一个十一岁] 可以理解。把那张纸揉成一团扔掉,直到你可以一口气把它写下来而不会出错。然后回到电脑前,试着编写你刚刚写的代码。

100 次中有 99 次你实际上会发现这可以帮助你解决你的问题,而无需问别人问题,因为 100 次中有 99 次我们的问题是由于我们自己对问题本身缺乏了解。试图(实际上)向你的祖母或 11 岁的孩子解释你的问题会迫使你抛弃一些让你眼花缭乱的假设,并在他们停止支付时让你目瞪口呆之前真正快速找到问题核心注意力。[我不是说你实际上和你的祖母/一个十一岁的孩子结对编程]

这是我为您设想的此类问题陈述的一个示例。这可能是不正确的,因为我不知道您的具体问题是什么:

We need a table that provides cross-reference notes about two other tables. 
There are different types of cross-reference (we use the column 're_id' to 
identify the type of cross-reference) and there are different types of notes 
(we use the columns 'up_id' as well as 'someValue') to store the actual notes.
The cross-reference is indicated with two columns 'some_id' which is the id
of the row in the 'some' table and 'someOther_id' which is the id of the row
in the 'someOther' table. There can be only one cross-reference between any one
row in the 'some' table and any one row in the 'someOther' table, but there can
be multiple cross-references from one specific row in the 'some' table to different
rows in the 'someOther' table.

使用上述问题陈述,我会将主键从自动增量切换为两列主键(some_id,someOther_id)并删除所有辅助键!

但我希望您意识到您的实际解决方案实际上可能不同,因为您的问题陈述与我的猜测不同。

于 2012-10-22T10:01:25.940 回答
3

来自MySQL 文档

如果表包含一AUTO_INCREMENT列并INSERT ... UPDATE插入一行,则该LAST_INSERT_ID()函数返回该AUTO_INCREMENT值。如果语句改为更新一行,LAST_INSERT_ID()则没有意义。但是,您可以使用LAST_INSERT_ID(expr). 假设 id 是AUTO_INCREMENT列。要使LAST_INSERT_ID()更新有意义,请按如下方式插入行:

INSERT INTO table (a,b,c) VALUES (1,2,3)
   ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
于 2012-10-22T09:39:43.727 回答
1

相同的查询工作正常,将 columns_value DUPLICATE KEY UPDATE 更改为实际列 some_value

小提琴演示

问题是

他应该在列(up_id)上定义表上的唯一唯一约束。

我刚刚用 unique constraint up_id 列更改了你的表,

Fiddle_demo

于 2012-10-22T09:38:17.707 回答