首先我们得明白在数据库中单引号是用来字符串引用的,不管是数字还是时间,当你用单引号引用起来之后,数据库就会将他当成字符串来对待.
我们先看下面两个语句:
其中 age 字段是 varchar 格式,全部都是数字,不要问我既然都是数字的为什么不用 num 类型.
select from users where age > 30
select from users where age > '30'
当两个语句执行的时候,发现第一个语句能准确的筛选出我们想要的结果,第二个语句虽然也可以执行,但筛选出来的结果中 age 比 30 小的也出现了.
这时候我们疑问就来了,按理来说,第二个应该才是正确的写法,为什么第二个反而得不到我们想要的结果,第一个却可以呢?
首先我们先看第一个问题:
select * from users where age > '30'
当 30 加上单引号,其实就变成了两个字符串之间比较大小了.
假如有一条 age 的值为 4,当数据库将'4'和'30'来比较大小的时候,第一步会用空格补全位数,实际比较的是'4'和'30',然后从左至右依次比较 ascii 码大小,4 的 ascii 码是 52,3 的 ascii 码是 51,所以'4'就比'30'大了,也就出现在我们的筛选结果中了
如果比较的是'3'和'30',同样的也会先去补全位数,第一位都是 3 然后比较第二位,第二位空格的 ascii 码 32,0 的 ascii 码是 48,因此'3'就比'30'小了,好像没毛病,不过我们得明白其中的道理.
梳理下规则
1. 用空格补全字符长度短的一方;
2. 从左至右依次比较 ascii 码的大小
第二个问题:
第二个问题涉及到了数据隐式转换.
在 oracle 中,如果不同的数据类型之间关联,如果不显式转换数据,则它会根据以下规则对数据进行隐式转换.
什么意思呢,我们看上面的例子,age 为 varchar 类型时,30 为 num 类型,当我们执行
select * from users where age > 30
的时候,oracle 会把 age 的数据类型隐式转换为 num 型,上面的语句其实等同于
select * from users where to_number(age) > 30
数字类型比较大小,当然就没问题了,所以筛选出的结果就是我们期望看到的了;
当然如果 age 字段里面有不能 to_number 的值,例如里面有一条记录 age 是'二十八',那么上面的语句就会报错了.
peace~
来源: http://www.jianshu.com/p/edc915d20ad3