在插入错误时保留顺序主键

时间:2010-08-19 17:54:21

标签: mysql unique

我在mysql中的create table命令是

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')

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

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')

1 个答案:

答案 0 :(得分:0)

这看起来像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