一位同事让我意识到一个非常奇怪的MySQL行为.
假设您有一个包含auto_increment字段的表和另一个设置为唯一的字段(例如用户名字段).当尝试插入具有已存在于表中的用户名的行时,插入失败,如预期的那样.但是,在多次尝试失败后插入有效的新条目时,可以看到auto_increment值增加.
例如,当我们的最后一个条目看起来像这样......
ID: 10
Username: myname
Run Code Online (Sandbox Code Playgroud)
...我们在下一次插入时尝试五个具有相同用户名值的新条目,我们将创建一个新行,如下所示:
ID: 16
Username: mynewname
Run Code Online (Sandbox Code Playgroud)
虽然这本身并不是一个大问题,但似乎是一个非常愚蠢的攻击向量,通过使用失败的插入请求充斥它来杀死表,正如MySQL参考手册所述:
"如果值大于可以存储在指定整数类型中的最大整数,则不会定义自动增量机制的行为."
这是预期的行为吗?
使用MySQL 5.1.49,我正在尝试实现一个标记系统我遇到的问题是带有两列的表:id(autoincrement),tag(unique varchar) (InnoDB)
使用查询时,即使忽略插入INSERT IGNORE INTO tablename SET tag="whatever",自动增量id值也会增加.
通常这不会是一个问题,但我希望很多可能的尝试为这个特定的表插入重复项,这意味着我id的新行的字段的下一个值将跳得太多.
例如,我最终会得到一张表3行但不好id的表
1 | test
8 | testtext
678 | testtextt
Run Code Online (Sandbox Code Playgroud)
此外,如果我不这样做INSERT IGNORE并且只是定期INSERT INTO处理错误,则自动增量字段仍会增加,因此下一个真正的插入仍然是错误的自动增量.
如果有INSERT重复的行尝试,有没有办法停止自动增量?
正如我对MySQL 4.1的理解,这个值不会增加,但我想做的最后一件事是要么SELECT提前做很多语句来检查标签是否存在,或者更糟糕的是,降级我的MySQL版本.
我在这里问了类似的问题......
但我无法得到足够的答案来解决我的问题,所以我不得不再次提问......
我有下表......
**
任何想要播放数据的人请在http://sqlfiddle.com/#!9/a0807进行测试
**
Table1
IDA colB colC
111 a w
222 b w
333 c s
444 b g
Table2
IDB colB colC
11 w f
12 w r
13 s g
Table3
IDA IDB
111 11
222 12
333 13
444 14
Run Code Online (Sandbox Code Playgroud)
下面的代码将从table1复制或插入到表中没有问题,但是有错误的table2 IDB(因为table2 IDB值应该从内部连接到table3)
INSERT INTO table2 SELECT * FROM table1 WHERE IDA = 111
Run Code Online (Sandbox Code Playgroud)
但是将所有从table1复制到table2,这是错误的......
所以,我所做的是......以下的内部联系......但是没有工作......
INSERT INTO table2
(SELECT * FROM table1 b
LEFT JOIN table3 c ON c.IDA = …Run Code Online (Sandbox Code Playgroud) $sql_career = "REPLACE INTO career
(id, battletag, lastHeroPlayed, lastUpdated, monsters, elites, hardcoreMonsters, barbarian, crusader, demonhunter, monk, witchdoctor, wizard, paragonLevel, paragonLevelHardcore)
VALUES
('', '$battletag', '$lastHeroPlayed', '$lastUpdated', '$monsters', '$elites', '$hardcoreMonsters', '$barbarian', '$crusader', '$demonhunter', '$monk', '$witchdoctor', '$wizard', '$paragonLevel', '$paragonLevelHardcore')";
Run Code Online (Sandbox Code Playgroud)
ID自动递增。
battletag是独特的。
其他一切都会随着时间而改变。因此,如果条目已经存在,我想替换或更新条目battletag而不创建新的id。如果它不存在,我希望它创建一个新条目,让id该唯一的自动增量battletag。
这可以解决一个问题:
$sql_career = "
insert INTO career
(id, battletag, lastHeroPlayed)
VALUES
(NULL, '$battletag', $lastHeroPlayed)
on duplicate key
update lastHeroPlayed=$lastHeroPlayed;
";
Run Code Online (Sandbox Code Playgroud)
例如,如果我加载两个唯一的行,则每个行的 ID 自动递增到 1,然后递增到 2。然后,如果我加载的行具有现有行之一的唯一键的重复项(然后按预期更新),这实际上会触发自动增量。因此,如果我添加第三个唯一行,其编号将是 4 而不是 3。
我怎样才能解决这个问题?