INSERT IGNORE还是自动增量,替代SQL查询?

时间:2011-08-01 12:02:42

标签: mysql sql

$q = $db->prepare('INSERT IGNORE INTO Cities (Name,Stamp) VALUES (?,?)');
$q->execute(array($city,$stamp));

我正在运行此代码以在Cities表中插入新城市。我只是注意到每个查询都会增加id字段,这不是我想要的。这并不像我依赖于无间隙的id值,但每次运行代码时都会增加它是荒谬的。

那么,我可以运行什么样的智能SQL查询来为我提供相同的功能而无需执行两个查询(首先是SELECT,然后是INSERT)而不是auto_increment?

表格描述:

    Field       Type         Null   Key Default Extra
    id          int(11)      NO     PRI NULL    auto_increment
    Name        varchar(100) YES    UNI NULL     
    countryid   int(11)      YES        NULL     
    Stamp       int(11)      YES        NULL     
    uid         int(11)      YES        NULL    

代码:

INSERT INTO Cities (Name,Stamp) VALUES (?,?) ON DUPLICATE KEY UPDATE Name = Name

增加我桌子上的值。 MySQL版本是5.5.9。数据库引擎是innoDB。


可能是这个错误:http://bugs.mysql.com/bug.php?id=28781 如果你向下滚动到底部,你可以看到它仍然是一个问题,三年后......

3 个答案:

答案 0 :(得分:3)

请参阅Bug #42497: V5.1 AUTO_INCREMENT gaps with InnoDB when using INSERT IGNORE(这实际上不是错误)。

您需要配置innodb_autoinc_lock_mode=0或更改语句。有关详细信息,请参阅相关的AUTO_INCREMENT Handling in InnoDB文档。

这是您所看到的行为的摘要。在MySQL 5.1.22中引入了在InnoDB中分配自动增量值的新方法:

  

对于要插入的行数已知的INSERT语句   在处理语句之初,InnoDB快速分配   没有锁定所需的自动增量值数,   但只有在没有并发会话的情况下才会持有   表级AUTO-INC锁(因为其他语句将是   在进行时逐个分配自动增量值)。更多   确切地说,这样的INSERT语句获得自动增量值   在未被保持的互斥锁(轻量级锁)的控制下   直到声明完成,但仅限于声明的持续时间   分配过程。

简而言之,MySQL能够确定您的语句将插入多少行,并预先分配自动增量值。这可以防止多个并发语句交错自动增量值。但是,一旦分配了该号码,就不能再使用它。这引入了自动增量值中存在间隙的可能性。

以下语句适用于我,不增加自动增量值,并使用innodb_autoinc_lock_mode = 1(默认设置):

INSERT INTO Cities (Name, Stamp)
SELECT $Name, $Stamp
  FROM Cities
 WHERE NOT EXISTS (
    SELECT NULL
      FROM Cities
     WHERE Name = $Name
);

答案 1 :(得分:0)

姓名或邮票是否唯一?

否则,值会增加,因为插入了相同的行。但我想你应该注意到你的桌子上有那么多行吗?

答案 2 :(得分:-1)

$q = $db->prepare('INSERT INTO Cities (Name,Stamp) VALUES (?,?) ON DUPLICATE KEY UPDATE Name = Name');
$q->execute(array($city,$stamp));