我自己也遇到了这个限制,但尽管网上有很多闲聊,但我从未见过对为什么时间数据类型的上限和下限是这样的解释。http://dev.mysql.com/doc/refman/5.7/en/time.html的官方推荐信说
时间值可以从'-838:59:59‘到'838:59:59’之间。时间部分可能很大,因为时间类型不仅可以用来表示一天中的时间(必须小于24小时),而且可以用来表示经过的时间或两个事件之间的时间间隔(可能远远大于24小时,甚至是负的)。
但我并不想知道为什么时间部分被允许“那么大”,而是为什么它被切断了它所在的位置。那么多小时的日子似乎没有任何意义,或者,如果我试着想象有多少秒可以作为一个整数存储的话。那为什么是靶场?
发布于 2016-09-01 21:48:06
TIME值总是存储在MySQL中的3个字节上。但是格式在5.6.4版上发生了变化。我怀疑这不是第一次发生变化。但另一个变化,如果有一个,发生在很久以前,没有公开的证据证明它。MySQL在GitHub上的源代码历史从版本5.5开始(最早的提交是从2008年5月开始),但我正在寻找的更改发生在2001-2002年前后(MySQL 4是在2003年启动的)。
如文档中所述,当前格式使用6位秒(可能值:0到63)、6位(分钟)、10位(可能值:0到1023)、1位表示符号(添加前面提到的间隔的负值),1位未使用并标记为“为未来扩展保留”。
它为处理时间组件(小时、分钟、秒)进行了优化,并且不会浪费太多空间。使用这种格式,可以在-1023:59:59和+1023:59:59之间存储值。然而,MySQL将时间限制在838上,可能是为了与不久前编写的应用程序进行向后兼容性,而我认为这是限制。
在5.6.4版本之前,TIME值也存储在3个字节上,组件被打包为days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds。这种格式是为使用时间戳而优化的(因为它实际上是一个时间戳)。使用这种格式,可以将值存储在关于-2330到+2330小时的范围内。虽然有这么大范围的值可用,但MySQL仍然将-838的值限制为+838小时。
在bug #11655 4上有MySQL,可以使用嵌套的SELECT语句返回-838..+838范围之外的TIME值。这不是一个特性,而是一个bug,而且它是固定的。
将值限制在此范围内并主动更改任何在其外部生成TIME值的代码的唯一原因是向后兼容性。
我怀疑MySQL 3使用了一种不同的格式,由于数据打包的方式,它将有效值限制在-838..+838小时范围内。
通过查看当前的MySQL源代码,我发现了一个有趣的公式:
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)让我们暂时忽略上面使用的名称的MAX部分,只记住TIME_MAX_MINUTE和TIME_MAX_SECOND是00和59之间的数字。该公式只是将小时、分钟和秒串联成一个整数。例如,值170:29:45变为1702945。
这个公式引发了以下问题:假设TIME值存储在带符号的3个字节上,那么以这种方式表示的最大正值是多少?
我们正在寻找的值是0x7FFFFF,它在十进制表示法中是8388607。由于最后四个数字(8607)应该被读取为分钟(86)和秒(07),并且它们的最大有效值是59,所以使用上面的公式可以存储在带符号的3个字节上的最大值是8385959。就像TIME是+838:59:59。塔-达!
你猜怎么着?上面列出的C代码片段是从以下内容提取的:
/* Limits for the TIME data type */
#define TIME_MAX_HOUR 838
#define TIME_MAX_MINUTE 59
#define TIME_MAX_SECOND 59
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)我确信这就是MySQL 3在内部保存TIME值的方式。这种格式限制了范围,而对后续版本的向后兼容性要求将这种限制传播到了我们的时代。
https://stackoverflow.com/questions/39259910
复制相似问题