起因
因为技术的细节有很多,我习惯做笔记,特别是一些新奇的、在我认知之外的,我更喜欢记录一下。今天我在复习mysql时,看我之前的笔记,看到了这么一条笔记
对于我自己记的东西,很多时候我都是深信不疑,因为我肯定是经过验证或者很肯定的事情,我才记的。但是翻笔记的时候离我做笔记的时候已经过了好久了,所以我不是很肯定这条笔记的正确性。于是我百度了一下,惊奇的发现,百度上全都是这么一个结论:between是闭区间,压根没有提“应用在字符上是左闭右开”的事情,我当时就觉得很怪异,因为如果真的有这条结论的话,网上应该有相关的文章才对。
验证
既然网上没有结论,那我自己进行验证。
测试表:
测试数据:
测试SQL
三条SQL全都把所有的数据都查询出来了,那么我的笔记“between……and应用在字符上是左闭右开”就不对了,那为什么我会记这条记录呢?
溯源
我依稀记得是我在b站看老杜的mysql视频的时候记的这条笔记,老杜mysql 视频连接:https://www.bilibili.com/video/BV1fx411X7BD。
翻了两下目录,找到了我记这条笔记的原因,的确是老杜说的,在这一集 https://www.bilibili.com/video/BV1fx411X7BD?p=14 的2分钟处,老杜推导出来这么一个结论,因为这个结论当时是老杜在视频中推导出来的,所以我自己就没有验证,直接记录的,但是我上面在验证的时候,发现结论并不是老杜推导的那样。
当时看的时候没有想到,现在看来,其实老杜的推导不严谨,所以得出的结论不正确,建议读者看一下这个视频https://www.bilibili.com/video/BV1fx411X7BD?p=14,很短,总共就5分钟,开个两倍就两分钟。看了之后更能理清事情的来龙去脉,我为什么要记“between……and……应用在数字上的时候,是闭区间。应用在字符上时,是左闭右开”这条笔记,以及接下来的复盘。
复盘
老杜的推导不正确,为什么说不正确呢?我简单的模拟一下当时老杜数据库里的数据,还是上面的那张表,多加了几条数据,如下
当时老杜的第一条测试SQL是这样的
查出来的数据是这样的
咋一看,好像是左闭右开的,因为name为CD的那条记录没有被查出来
老杜为了严谨,然后又测试了一条SQL
查询结果是这样
name为DE的那条记录没有被查询出来,好像也验证了左闭右开,但实际上真的是这样吗?
什么为闭?能取到边界值,即为闭,但是第一条测试的右边界是“C”并不是“CD”,第二条测试的右边界是“D”,不是“DE”,这怎么能验证呢?
那我们来试试右边界为CD和DE的时候是怎么样的,
果然,右边界为CD时能查询到name为CD的那条记录,右边界为DE时能查询到name为DE的那条记录。
那这么一说,是包含边界值,但是也不对啊,左边界是A,为何能查询到name为AB的记录呢?
真相
左右边界都为一个单字符,为啥左边的就能取到,右边的就不能取到呢?相信有的小伙伴已经大概猜到了,因为左边界一个单字符A是小于AB的,所以能查到AB,而右边界的C也是小于CD,所以CD不在AC范围内,查询不到。
其实字符串在比较是是按照ASCII码进行比较的(包括大于、小于、等于和between……and……),在mysql中是这样的,从左边第一个字符开始比,相同则比较下一个字符,如果其中一个字符串没有下一个字符,则另一个大。可以用一些特殊符号结合其ASCII值用大小于来进行测试,
所以,AB比A大,CD比C大,所以A~C能查询到AB,并不能查询到CD。
所以最终结论是:
- between……and……是闭区间,两边界都能取到,无论是应用在数字还是字符上,
- MySQL中字符串比较是从左到右按位按照其ASCII值来进行比较的,