【问题标题】:Keep sequential primary key in error insert在错误插入中保持顺序主键
【发布时间】:2010-08-19 17:54:20
【问题描述】:

我在mysql中的创建表命令是

CREATE TABLE `map` (
  `id`  int(4) AUTO_INCREMENT NOT NULL,
  `city`    varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE = InnoDB;

CREATE UNIQUE INDEX `map_city_idx`
  ON `map`
  (`city`);

初始值,如:

id(1),city('Banda Aceh')
id(2),city('Medan')

下一个插入是 city('Medan'),所以它是错误的,因为 city 列是唯一的。下一个insert是city('Bengkulu'),最终的table结果是

id(1), city('Banda Aceh')
id(2), city('Medan')
id(4), city('Bengkulu')

不是 id(3) 而是 id(4)。那么即使之前有/曾经插入错误,我怎么能保持顺序主键呢?

id(1), city('Banda Aceh')
id(2), city('Medan')
id(3), city('Bengkulu')

【问题讨论】:

  • 为什么你需要你的键是连续的?如果/当您无论如何执行删除操作时,您的 id 中都会有“空白”,因此您不应该指望您的键是连续的。

标签: mysql unique


【解决方案1】:

这看起来像 InnoDB 的行为。 InnoDB 回滚事务,但无法恢复自动增量键,因为它可能被其他人使用。这不会发生在 MyISAM 表中,但是使用 InnoDB,您可以使用事务来阻止它。我会用 php 写这个,但你可以用任何你想要的语言重复它:

mysql_query('START TRANSACTION');
//query if it exists and lock the record
$r = mysql_query('SELECT id FROM map WHERE city="Medan" FOR UPDATE'); 
if(mysql_num_rows($r)>0){
  //already exists
  // there are better ways to do this, buy you got the idea.
  list($id) = mysql_fetch_row($id);
  mysql_query('ROLLBACK'); // release the lock
}else{
  // does not exists - insert it
  mysql_query('INSERT INTO map(city) VALUES("Medan")');
  $id =  mysql_insert_id();
  mysql_query('COMMIT'); //commit and release the lock
}
//... here $id will be id of 'Medan' city regardless if it is inserted now
//  or it is duplicate and there will be no autoincrement key holes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 2021-08-19
    • 2023-03-10
    相关资源
    最近更新 更多