4

我的问题与为什么在插入失败时 MySQL 自动增量增加相同?,但与其增加我的id字段,我宁愿只重写给INSERT我带来麻烦的查询。假设我有一个包含两个字段的数据库,id并且username,其中id是主键并且username是唯一键。我本质上是在寻找可以做到的语法INSERT...IF NOT EXISTS。现在,我愿意

INSERT INTO `table`(`username`) 
    VALUES ('foo') 
    ON DUPLICATE KEY UPDATE `id`=`id`

我只有一个线程写入数据库,所以我不需要任何并发保护。建议?

4

5 回答 5

6

你应该使用这个:

INSERT INTO tableX (username) 
  SELECT 'foo' AS username
  FROM dual
  WHERE NOT EXISTS
        ( SELECT *
          FROM tableX 
          WHERE username = 'foo'
        ) ;

如果要包含更多列的值:

INSERT INTO tableX (username, dateColumn) 
  SELECT 'foo'                       --- the aliases are not needed             
       , NOW()                       --- actually
  FROM dual
  WHERE NOT EXISTS
        ( SELECT *
          FROM tableX 
          WHERE username = 'foo'
        ) ;                      
于 2012-05-15T12:21:19.553 回答
4

我认为您不能阻止计数器增加,原因在您所链接的问题的答案中给出。

你有三个选择:

  1. 与跳过的标识符一起生活;您真的希望用完 64 位吗?

  2. 在尝试之前检查现有记录是否存在INSERT

    DELIMITER ;;
    
    IF NOT EXISTS (SELECT * FROM `table` WHERE username = 'foo') THEN
      INSERT INTO `table` (username) VALUES ('foo');
    END IF;;
    
    DELIMITER ;
    

    或者,更好的是,使用FROM dual WHERE NOT EXISTS ...@ypercube 建议的形式。

  3. 每次插入后重置计数器。如果INSERT在存储过程中执行操作,您可以使用重复键错误处理程序来执行此操作:

    DELIMITER ;;
    
    CREATE PROCEDURE TEST(IN uname CHAR(16) CHARSET latin1) BEGIN
      DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' BEGIN
        -- WARNING: THIS IS NOT SAFE FOR CONCURRENT CONNECTIONS
        SET @qry = CONCAT(
          'ALTER TABLE `table` AUTO_INCREMENT = ',
          (SELECT MAX(id) FROM `table`)
        );
        PREPARE stmt FROM @qry;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        SET @qry = NULL;
      END;
      INSERT INTO `table` (username) VALUES (uname);
    END;;
    DELIMITER ;
    

    牢记@ypercube 在他的评论中提出的关于此策略的(有效)担忧,您可以改用:

    SELECT AUTO_INCREMENT - 1
    FROM   INFORMATION_SCHEMA.TABLES
    WHERE  table_schema = 'db_name' AND table_name = 'table';
    
于 2012-05-15T12:21:56.853 回答
2

您可以在插入失败后简单地重置自动增量字段

ALTER TABLE 表名 AUTO_INCREMENT =1;

这不会将自动增量重置为 1,但会将其重置为当前最大值加一

另请注意,您连接到数据库的用户应该对目标表具有更改权限

于 2015-03-25T21:15:12.457 回答
0

您还可以在插入该用户之前检查该用户之前是否已插入,这将需要对您的数据库进行额外调用,但是,如果该用户已经存在,您可以返回您找到的信息并避免虚假插入。

于 2014-11-06T13:26:34.553 回答
-1

使用INSERT IGNORE INTO table. 检查下面的帖子

http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html

你可以这样做:

INSERT INTO `table`(`username`) 
VALUES ('foo')      
ON DUPLICATE KEY UPDATE `username`= 'foo' 

或者

INSERT IGNORE INTO `table`
SET `username` = 'foo'
于 2012-05-15T11:48:42.813 回答