数据库原理课本中模糊匹配 like 下划线匹配多字符问题
2015-04-17 12:59
253 查看
在数据库系统概论第四版第三章96页的字符匹配当中指出,_(下划线)代表任意单个字符。根据书中前面的sql语句建立表格,并插入数据,执行查找姓刘的同学的记录
USE school
GO
SELECT *
FROM Student
WHERE Sname LIKE '刘_';
结果如下:
现在没有任何问题,是我们想要的结果,但是如果多打一个_(下划线)结果会是什么样呢?
原本应该只匹配三个字的Sname 的记录才输出,然而两个字的Sname的记录也输出了。
这结果让人感觉很蛋疼,为什么会是这个结果呢?我觉得这是这本的bug。那么问题究竟出来哪呢?
我们看一下建表的语句以及定义的数据类型:
CREATE TABLE Student --create student table
( Sno CHAR(9) PRIMARY KEY,
Sname
CHAR(20) NOT NULL UNIQUE,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20)
);
我们可以看到Sname的数据类型是CHAR类型,问题就出在这里。我们首先看一下CHAR和VARCHAR的区别(参考网友解释):
1. char类型:
对英文(ASCII)字符占用1个字节,对一个汉字占用2个字节,CHAR存储定长数据很方便,CHAR字段上的索引效率极高,比如定义char(10),那么不论你存储的数据是否达 到了10个字节,都要占去10个字节的空间。因为是固定长度,所以速度效率高。比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间。因为是固定长度,所以速度效率高。
2. VARCHAR存储变长数据
如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么“+1”呢?这一个字节用于保存实际使用了多大的长度。
Varchar类型:Varchar 的类型不以空格填满,而Char则会填充满为止,如varchar(100),但它的值只是"qian",所以它在数据库中存的值就是"qian",而char 不一样,如char(100),它的 值是"qian",而实际上它在数据库中是"qian "(qian后共有96个空格,就是把它填满为100个字节)。
注:由于char是以固定长度的,所以它的速度会比varchar快得多!但程序处理起来要麻烦一点,要用trim之类的函数把两边的空格去掉!
我们可以看到,根据书中定义的Sname是定长CHAR型,长度为20,那么当存入一条记录,其中Sname是“刘晨”时,在数据库中“刘晨”的存储形式是前四个字节存姓名,后面18字节用空格补齐,而空格也是字符,_(下划线)也匹配它,所以执行sql语句进行模糊查询时将字符串长度小于3的也匹配出来。
那么如何解决这问题呢,我们重新建一个表,Sname定义为VARCHAR(20)类型,看一下结果:
我们可以看到,定义为VARCHAR类型后,由于字符串的长度就是存储长度,不存在用空格补全问题,所以输出结果正常。可以看出数据的定义还要是非常小心的,那么我们怎么可以避免这个问题我,我认为:
首先,要选择合适的数据类型。其次用先对安全的方法得到自己想要结果。
比如,我们可以用
SELECT *
FROM Student
WHERE Sname LIKE '刘%' AND LEN(Sname)=2;
语句,同样是在课本定义的数据库中得到我们想要的结果。
USE school
GO
SELECT *
FROM Student
WHERE Sname LIKE '刘_';
结果如下:
现在没有任何问题,是我们想要的结果,但是如果多打一个_(下划线)结果会是什么样呢?
原本应该只匹配三个字的Sname 的记录才输出,然而两个字的Sname的记录也输出了。
这结果让人感觉很蛋疼,为什么会是这个结果呢?我觉得这是这本的bug。那么问题究竟出来哪呢?
我们看一下建表的语句以及定义的数据类型:
CREATE TABLE Student --create student table
( Sno CHAR(9) PRIMARY KEY,
Sname
CHAR(20) NOT NULL UNIQUE,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20)
);
我们可以看到Sname的数据类型是CHAR类型,问题就出在这里。我们首先看一下CHAR和VARCHAR的区别(参考网友解释):
1. char类型:
对英文(ASCII)字符占用1个字节,对一个汉字占用2个字节,CHAR存储定长数据很方便,CHAR字段上的索引效率极高,比如定义char(10),那么不论你存储的数据是否达 到了10个字节,都要占去10个字节的空间。因为是固定长度,所以速度效率高。比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间。因为是固定长度,所以速度效率高。
2. VARCHAR存储变长数据
如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么“+1”呢?这一个字节用于保存实际使用了多大的长度。
Varchar类型:Varchar 的类型不以空格填满,而Char则会填充满为止,如varchar(100),但它的值只是"qian",所以它在数据库中存的值就是"qian",而char 不一样,如char(100),它的 值是"qian",而实际上它在数据库中是"qian "(qian后共有96个空格,就是把它填满为100个字节)。
注:由于char是以固定长度的,所以它的速度会比varchar快得多!但程序处理起来要麻烦一点,要用trim之类的函数把两边的空格去掉!
我们可以看到,根据书中定义的Sname是定长CHAR型,长度为20,那么当存入一条记录,其中Sname是“刘晨”时,在数据库中“刘晨”的存储形式是前四个字节存姓名,后面18字节用空格补齐,而空格也是字符,_(下划线)也匹配它,所以执行sql语句进行模糊查询时将字符串长度小于3的也匹配出来。
那么如何解决这问题呢,我们重新建一个表,Sname定义为VARCHAR(20)类型,看一下结果:
我们可以看到,定义为VARCHAR类型后,由于字符串的长度就是存储长度,不存在用空格补全问题,所以输出结果正常。可以看出数据的定义还要是非常小心的,那么我们怎么可以避免这个问题我,我认为:
首先,要选择合适的数据类型。其次用先对安全的方法得到自己想要结果。
比如,我们可以用
SELECT *
FROM Student
WHERE Sname LIKE '刘%' AND LEN(Sname)=2;
语句,同样是在课本定义的数据库中得到我们想要的结果。
相关文章推荐
- 使用模糊查询Like时中文匹配下划线通配符无效的问题
- SQL搜索下划线,like中不能匹配下划线的问题
- SQL搜索下划线,like中不能匹配下划线的问题
- 解决like中无法匹配下划线的问题
- sql 字符带下划线匹配问题
- SQL搜索下划线,like中不能匹配下划线的问题
- jsp实现的数据库模糊搜索(可以自己设定匹配字符个数)
- sql server中like无法匹配下划线问题解决方案
- sql查询模糊匹配Like的没数据一个问题
- 解决like中无法匹配下划线的问题
- jsp实现的数据库模糊搜索(可以自己设定匹配字符个数)
- SqlServer nvarchar中的中文字符匹配,更改SqlServer实例和数据库排序规则的办法
- 关于字符匹配所引起的的问题
- easyui datagrid combobox 模糊匹配的问题
- 数据库禁止模糊匹配的情况下实现模糊匹配以及分页展示
- 模糊匹配数据库中的json字段
- 关于打开现有项目时数据库连接配置遇到的问题 连接字符串中的数据源值指定未安装的SQL Server的实例。要解决此问题,可选择安装匹配的SQL Server实例或修改连接字符串中的数据源值
- 关于数据库多字段匹配问题
- 百度编辑器向数据库提交数据后字符转义的问题
- Oracle中使用escape关键字实现like匹配特殊字符,以及&字符的转义