2010-08-19 28 views
1

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

下一个插入的城市(“棉兰”),所以它的错误因为城市列是独一无二的。接下来的插入是城市( '明古鲁'),决赛桌的结果是

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

为什么你需要你的密钥是连续的?无论如何,如果/当您执行删除操作时,您的ID中都会有“空白”,所以您不应该指望您的密钥是连续的。 – 2010-08-19 17:58:45

回答

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