插入重复键 - 跳过自动递增 ID
Insert into on duplicate key - auto increment id skipped
我目前有一个 SQL 执行脚本,它更新重复键上的行,如下所示。
$stmt = $dbCon->prepare("INSERT INTO videos_rating (videos_rating_video_fk, "
. " videos_rating_user_fk, "
. " videos_rating_rating) "
. " VALUES (:video_id, "
. " :user_id, "
. " :video_rating) "
. " ON DUPLICATE KEY UPDATE videos_rating_rating = :video_rating");
脚本运行良好,但有没有办法防止自动增量列不同步?
假设我们从一个空的 table 开始,然后我对视频进行评分,然后创建一个 ID 为 1 的行,然后用户通过对同一视频的评级较低或较高,并且该行将被更新,因为它现在是重复键,肯定没问题。
问题是这样的
下次其他用户评价新视频时,该行现在将从 id 3 而不是 2 开始?
table 看起来像这样
id | videos_rating_user_fk | videos_rating_rating
1 | 1 | 4
3 | 2 | 5
我找不到类似的问题,即使我发现没有其他人对此感到困扰的可能性很小,如果是这样,请让我参考那个 post。
我知道 id 不应该 'look good' 但是 id 从 30 - 51 - 82 - 85 - 89 等跳来跳去是很烦人的达到了大整数?我不是说我会去那么高但仍然。
让我们假设您的 table 是这样构建的:
videos_rating_video_fk | videos_rating_user_fk | videos_rating_rating
-----------------------+-----------------------+----------------------
第一个键videos_rating_video_fk
应该是外键而不是自增主键。
如果用户 1 和 2 投票给具有 id
1 的视频,您的 table 应该 看起来像这样:
videos_rating_video_fk | videos_rating_user_fk | videos_rating_rating
-----------------------+-----------------------+----------------------
1 | 1 | 4
1 | 2 | 5
对于那种table,主键应该是两个外键的组合并且是唯一的。用户只能为视频投票一次(唯一投票 = 唯一密钥)。一个视频可以被多个用户投票,用户可以为多个视频投票。
我建议您查看用于构建具有完整性约束和主键创建的 tables 的 Merise 方法。
我假设您正在使用默认的 InnoDB 引擎。在那种情况下,"problem" 是引擎在知道它是否重复之前将 "reserve" id。一旦 id 为 "reserved",它就不能被释放,因为另一个线程(另一个用户)可能会在 "same" 时间执行插入到同一个 table。还有其他方法可以在不删除任何行的情况下在 AUTO_INCREMENT 列中获得间隙。一种是回滚事务时。
您可以尝试 "reset" 每次插入
后的下一个 AUTO_INCREMENT 值
alter table videos_rating auto_increment = 1;
但我不能说在 运行ning 实时环境中执行此语句时您可能 运行 会遇到什么问题。而且我不会找出答案。
请注意,这通常不是问题,因为您 运行 IODKU 语句(通常)在 table 上不需要 AUTO_INCREMENT 列。正如 Cid 在他的回答中所写,您可以删除 id
列并将您的唯一键定义为主键。
与 "burning" 的 ID 一起生活。 AUTO_INCREMENT
保证不允许重复值,不 不提供任何其他保证。
ID 可能 'burned'还有大约 4 种其他方式:REPLACE
、Multi-Master / Galera、IGNORE
、DELETE
,可能更多。
IODKU 在发现该语句将变成 UPDATE
并且不需要该 id 之前迅速获取了一个 id。否则可能会严重影响性能。
确认一下,Paul Spiegel 的回答帮助我解决了问题。我有一些 'Upsert' SQL 查询使用 ON DUPLICATE KEY UPDATE
来确定是创建新行还是更新现有行。在频繁更新行的地方,分配的 Id 中的跳跃很大。
the "problem" is that the engine will "reserve" the id before it knows if it's a duplicate or not.
我通过将 SQL 代码分解为单独的 INSERT 和 UPDATE 语句解决了这个问题。我不再看到这个问题。
我目前有一个 SQL 执行脚本,它更新重复键上的行,如下所示。
$stmt = $dbCon->prepare("INSERT INTO videos_rating (videos_rating_video_fk, "
. " videos_rating_user_fk, "
. " videos_rating_rating) "
. " VALUES (:video_id, "
. " :user_id, "
. " :video_rating) "
. " ON DUPLICATE KEY UPDATE videos_rating_rating = :video_rating");
脚本运行良好,但有没有办法防止自动增量列不同步?
假设我们从一个空的 table 开始,然后我对视频进行评分,然后创建一个 ID 为 1 的行,然后用户通过对同一视频的评级较低或较高,并且该行将被更新,因为它现在是重复键,肯定没问题。
问题是这样的
下次其他用户评价新视频时,该行现在将从 id 3 而不是 2 开始?
table 看起来像这样
id | videos_rating_user_fk | videos_rating_rating
1 | 1 | 4
3 | 2 | 5
我找不到类似的问题,即使我发现没有其他人对此感到困扰的可能性很小,如果是这样,请让我参考那个 post。
我知道 id 不应该 'look good' 但是 id 从 30 - 51 - 82 - 85 - 89 等跳来跳去是很烦人的达到了大整数?我不是说我会去那么高但仍然。
让我们假设您的 table 是这样构建的:
videos_rating_video_fk | videos_rating_user_fk | videos_rating_rating
-----------------------+-----------------------+----------------------
第一个键videos_rating_video_fk
应该是外键而不是自增主键。
如果用户 1 和 2 投票给具有 id
1 的视频,您的 table 应该 看起来像这样:
videos_rating_video_fk | videos_rating_user_fk | videos_rating_rating
-----------------------+-----------------------+----------------------
1 | 1 | 4
1 | 2 | 5
对于那种table,主键应该是两个外键的组合并且是唯一的。用户只能为视频投票一次(唯一投票 = 唯一密钥)。一个视频可以被多个用户投票,用户可以为多个视频投票。
我建议您查看用于构建具有完整性约束和主键创建的 tables 的 Merise 方法。
我假设您正在使用默认的 InnoDB 引擎。在那种情况下,"problem" 是引擎在知道它是否重复之前将 "reserve" id。一旦 id 为 "reserved",它就不能被释放,因为另一个线程(另一个用户)可能会在 "same" 时间执行插入到同一个 table。还有其他方法可以在不删除任何行的情况下在 AUTO_INCREMENT 列中获得间隙。一种是回滚事务时。
您可以尝试 "reset" 每次插入
后的下一个 AUTO_INCREMENT 值alter table videos_rating auto_increment = 1;
但我不能说在 运行ning 实时环境中执行此语句时您可能 运行 会遇到什么问题。而且我不会找出答案。
请注意,这通常不是问题,因为您 运行 IODKU 语句(通常)在 table 上不需要 AUTO_INCREMENT 列。正如 Cid 在他的回答中所写,您可以删除 id
列并将您的唯一键定义为主键。
与 "burning" 的 ID 一起生活。 AUTO_INCREMENT
保证不允许重复值,不 不提供任何其他保证。
ID 可能 'burned'还有大约 4 种其他方式:REPLACE
、Multi-Master / Galera、IGNORE
、DELETE
,可能更多。
IODKU 在发现该语句将变成 UPDATE
并且不需要该 id 之前迅速获取了一个 id。否则可能会严重影响性能。
确认一下,Paul Spiegel 的回答帮助我解决了问题。我有一些 'Upsert' SQL 查询使用 ON DUPLICATE KEY UPDATE
来确定是创建新行还是更新现有行。在频繁更新行的地方,分配的 Id 中的跳跃很大。
the "problem" is that the engine will "reserve" the id before it knows if it's a duplicate or not.
我通过将 SQL 代码分解为单独的 INSERT 和 UPDATE 语句解决了这个问题。我不再看到这个问题。