【问题标题】:Prevent auto increment on duplicated entry?防止重复输入时自动递增?
【发布时间】:2025-05-25 00:20:02
【问题描述】:

我有一个名为url_info 的表格,表格的结构是:

url_info:

url_id ( auto_increment, primary key )
url ( unique,varchar(500) )

当我像这样插入表格时:

INSERT INTO url_info(url) VALUES('Tom');
INSERT INTO url_info(url) VALUES('Jerry');

输出是:

1 Tom
2 Jerry

当我这样插入时

INSERT INTO url_info(url) VALUES('Tom');
INSERT INTO url_info(url) VALUES('Tom');
INSERT INTO url_info(url) VALUES('Jerry');

输出是

1 Tom
3 Jerry

当我尝试插入重复条目时,自动增量 ID 会增加。我也试过Insert Ignore

当我尝试插入重复条目时如何防止它增加?

【问题讨论】:

  • 你的意思是说你不想插入重复值?
  • @mhasan :不插入重复值。当我尝试插入重复的 url 时,我只是不希望 id 自动增加
  • 唯一的解决办法是在插入前检查
  • 是的,如果插入失败,它会自动递增,Eduardo 是正确的。
  • 之前的检查会影响性能吗?

标签: mysql sql duplicate-removal


【解决方案1】:

可能值得创建一个存储过程来将您想要的内容插入到表中。但是,在存储过程中检查表中已有的项目。如果这些匹配您尝试插入的内容,则查询甚至不应该尝试插入。

即。该过程需要包含以下内容:

IF NOT EXISTS(SELECT TOP 1 url_id FROM url_info WHERE url = 'Tom')
INSERT INTO url_info(url) VALUES('Tom')

因此,在您的存储过程中,它看起来像这样(假设参数/变量已被声明)

IF NOT EXISTS(SELECT TOP 1 url_id FROM url_info WHERE url = @newUrl)
INSERT INTO url_info(url) VALUES(@newUrl)

【讨论】:

  • 没有。 Insert 不会触发任何 SP,但会触发。
  • 你在说什么?他不能创建一个存储过程,而只是执行 EXEC storedproc Tom ??
  • 好的,现在我了解您的方法了。始终调用带有参数的 SP 以插入表中。检查值是否存在。如果是,则停止处理,否则插入。也应该在 SP 上加锁。
【解决方案2】:

这是 InnoDB 中的预期行为。原因是他们希望尽快释放 auto_increment 锁以提高并发性。不幸的是,这意味着它们会在解决任何约束(例如 UNIQUE)之前增加 AUTO_INCREMENT 值。

您可以在 AUTO_INCREMENT Handling in InnoDB 上的手册中阅读更多关于该想法的信息,但不幸的是,该手册也是 buggy 并且没有说明为什么您的简单插入会给出不连续的值。

如果这对您来说是一个真正的问题并且您确实需要连续的数字,请考虑在您的服务器中将innodb_autoinc_lock_mode 选项设置为0,但不建议这样做,因为它会对您的数据库产生严重影响(您不能同时进行任何插入)。

【讨论】:

    【解决方案3】:

    Auto_increment 由引擎执行更新。这是在检查值是否为unique 之前完成的。而且我们无法回滚操作以恢复到以前的 auto_increment 值。

    因此NO 从您上次阅读auto_increment 的位置开始。

    auto_increment 字段上丢失一些中间值也不是问题。
    您可以存储到SIGNED INT 字段中的最大值是2^31-1 等于2,147,483,647。如果您大声读,它听起来20 亿+

    而且我认为它不会太小,不能满足您的要求。

    【讨论】:

      【解决方案4】:
      CREATE TABLE `url_info` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ;
      

      当我执行时:

      INSERT INTO url_info(url) VALUES('Tom');
      INSERT INTO url_info(url) VALUES('Tom');
      INSERT INTO url_info(url) VALUES('Jerry');
      

      我明白了:

      确保您的 ID 列也是唯一的。

      正如手册所说:

      一个 UNIQUE 索引创建一个约束,使得索引中的所有值 必须是不同的。如果您尝试添加一个带有 与现有行匹配的键值。此约束不适用 除 BDB 存储引擎外,为 NULL 值。对于其他发动机,一个 UNIQUE 索引允许包含多个 NULL 值的列 无效的。如果为 UNIQUE 索引中的列指定前缀值, 列值在前缀中必须是唯一的。

      【讨论】:

      • 当您声明将 url 作为唯一值时,您无法在该字段中插入重复项。这就是你想要的吗?
      • 当我尝试插入重复的网址时,我只是不希望 id 自动增加。
      • Duik,他想停止重复。问题是,因为表本身有检查而不是插入,所以插入失败,但作为保护表自动增量。