Сохраняйте последовательный первичный ключ при вставке ошибки - PullRequest
1 голос
/ 19 августа 2010

Моя команда создания таблицы в 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')

Следующая вставка - город («Медан»), поэтому это ошибка, потому что столбец города уникален. Следующая вставка - город ('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 голосов
/ 17 апреля 2011

Это похоже на поведение 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
...