我不知道INNODB
是否会出现这种情况,但我真的认为这很奇怪。
如果我使用与MYISAM
相同的SQL语句,则会发生预期的行为。
MYISAM
CREATE TABLE main_database.numero (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id)
) ENGINE = MYISAM DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
INSERT INTO main_database.numero VALUES(NULL); -- First, run once time ...
INSERT INTO main_database.numero SELECT NULL FROM main_database.numero; -- After, more 12 times = 4096 records
结果(预期行为):
现在,如果我使用完全相同的语句,则通知引擎为INNODB
。
INNODB
CREATE TABLE main_database.numero (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id)
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
INSERT INTO main_database.numero VALUES(NULL); -- First, run once time ...
INSERT INTO main_database.numero SELECT NULL FROM main_database.numero; -- After, more 12 times = 4096 records
结果(奇怪的结果-跳过数字序列):
事实上,两个引擎都在创建预期的4096条记录,但是我担心INNO
的行为,因为我正在将数据库从MYISAM
迁移到INNODB
,而我确实不知道会对我的应用程序产生多大的影响。
答案 0 :(得分:2)
需要auto_increment机制来生成唯一值,该值大于其先前生成的任何值。它不保证生成连续值。
这里有一些讨论:https://bugs.mysql.com/bug.php?id=57643
如实生成连续值几乎没有什么意义,因为任何其他值可能会由于其他原因而“丢失”:
自动增量值不会返回到任何类型的队列,因为与此同时其他并发会话可能会生成更多的id值。 InnoDB维护未分配的id值的池是不值得的,因为该池可能变得巨大且浪费。
此外,“丢失”一个ID值可能是适当的,否则有人会认为他们原本打算删除的行又回来了。
答案 1 :(得分:2)
总结此声明的原因,它是一个调度系统 我使用该语句创建日历表。
这完全不在您的问题范围之内,该问题与缺少ID有关。
但是,还有更好的方法来生成数字和/或日历表,然后多次重复INSERT ... SELECT
。
所有方法都可以直接与其他表结合使用,也可以用于填充(索引)(临时)表
用于生成号码。
如果您的MariaDB / MySQL版本支持Windows功能
SET SESSION cte_max_recursion_depth = 5000;
WITH RECURSIVE number_generator(number) AS (
SELECT 0
UNION ALL
SELECT number + 1 FROM number_generator
WHERE number BETWEEN 0 AND 4096
)
SELECT * FROM number_generator
对于不支持窗口功能的MariaDB / MySQL。
SELECT
number_generator.number
FROM (
SELECT
@row := @row + 1 AS number
FROM (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row1
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row2
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row3
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row4
CROSS JOIN (
SELECT @row := -1
) init_user_params
) AS number_generator
WHERE
number_generator.number BETWEEN 0 AND 4096
ORDER BY
number_generator.number ASC
用于生成日历
如果您的MariaDB / MySQL版本支持Windows功能
SET SESSION cte_max_recursion_depth = 5000;
WITH RECURSIVE number_generator(number) AS (
SELECT 0
UNION ALL
SELECT number + 1 FROM number_generator
WHERE number BETWEEN 0 AND 4096
)
SELECT CURRENT_DATE + INTERVAL number_generator.number DAY FROM number_generator
对于不支持窗口功能的MariaDB / MySQL。
SELECT
CURRENT_DATE + INTERVAL number_generator.number DAY
FROM (
SELECT
@row := @row + 1 AS number
FROM (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row1
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row2
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row3
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row4
CROSS JOIN (
SELECT @row := -1
) init_user_params
) AS number_generator
WHERE
number_generator.number BETWEEN 0 AND 4096
ORDER BY
number_generator.number ASC
CURRENT_DATE
只是一个示例,您也可以使用过去或将来的固定日期作为示例,例如,您可以使用'2019-03-01'
。
此外,+ INTERVAL number_generator.number DAY
还可以使用负数来生成该日期和其他值的过去列表,然后是DAY
,如果您想使用月份,可以使用MONTH
,想要年份使用YEAR