填充空的自动增量值

时间:2014-11-14 12:26:30

标签: sql sqlite

我有一张这种结构的桌子:

  

| ID |名称|

当我在表格中添加新行时,

id 正在递增。 例如,我有3行:

1|John
2|Bob
3|Alice

如果我删除 ID为 2 的行,则会有:

1|John
3|Alice

如果我不知道ID为空,如何插入 ID = 2 的新行?
(或者 - 如何插入具有未使用的id(自动增量)值的行?)
感谢。

3 个答案:

答案 0 :(得分:1)

您可以使用此查询获取最少未使用的ID。

   SELECT (Min(ID) + 1) AS NewIDToInsert 
   FROM TableName T2A
   WHERE NOT EXISTS (SELECT ID FROM TableName T2B WHERE T2A.ID + 1 = T2B.ID)  

答案 1 :(得分:0)

来自documentation

  

在INSERT上,如果不是ROWID或INTEGER PRIMARY KEY列   明确给出一个值,然后它会自动填充一个   未使用的整数,通常是当前最大的ROWID之一   正在使用。无论AUTOINCREMENT是否正确,都是如此   使用了关键字。

换句话说,您应该能够在执行插入时明确指定id,并且不会自动增量。

答案 2 :(得分:0)

我使用this answer编写了一个适用于的存储过程,该存储过程用最大ID填充空ID。

用法

SELECT
  *
FROM
  tableName
;
CALL sp_fill_empty_ids('tableName');

实施

DELIMITER $$
CREATE PROCEDURE sp_fill_empty_ids(IN tableName VARCHAR(64))
BEGIN
  SET @minEmptyId := 0;
  SET @maxId := 0;

  CALL statement(CONCAT('
  SET @maxId = (
    SELECT MAX(Id)
    FROM ', tableName,'
  );
  '));
  CALL statement(CONCAT('
    SET @minEmptyId = (
      SELECT (Min(ID) + 1) AS NewIDToInsert
      FROM ', tableName,' T2A
      WHERE NOT EXISTS (SELECT ID FROM ', tableName,' T2B WHERE T2A.ID + 1 = T2B.ID)
    );
  '));
  WHILE ( @minEmptyId <> (@maxId + 1) ) DO
    CALL statement(CONCAT('
      SET @minEmptyId = (
        SELECT (Min(ID) + 1) AS NewIDToInsert
        FROM ', tableName,' T2A
        WHERE NOT EXISTS (SELECT ID FROM ', tableName,' T2B WHERE T2A.ID + 1 = T2B.ID)
      );
    '));

    CALL statement(CONCAT('
    --     SELECT * FROM
        UPDATE
          ', tableName, '
        SET Id = @minEmptyId
        WHERE Id = @maxId
        ;
    '));

    SET @maxId = @minEmptyId
    ;

  END WHILE;
  CALL statement(CONCAT('
    ALTER TABLE ', tableName,'
    AUTO_INCREMENT = ', @minEmptyId))
  ;
END$$
DELIMITER ;

statement的实现方式:

DELIMITER $$
CREATE PROCEDURE statement(IN dynamic_statement TEXT)
BEGIN
      SET @dynamic_statement := dynamic_statement;
      PREPARE prepared_statement FROM @dynamic_statement;
      EXECUTE prepared_statement;
      DEALLOCATE PREPARE prepared_statement;
  END$$
DELIMITER ;