SQL语句中过滤条件字段使用了to_char函数导致查询结果不准确的问题

简介:

        在SQL查询数据时,对一个日期字段进行过滤,使用to_char函数可能会造成返回结果不准确的问题,下面将针对这个现象做出测试。

一、构建环境

1、连接数据库创建表

sqlplus scott/tiger
create table test_riqi(id number,rq date);
AI 代码解读

2、插入数据

image

二、测试

1、日期显示格式为DD-MON-RR

①查询日期大于2018.09.04的信息

SCOTT@vbox66in>select * from test_riqi where to_char(rq,'DD-MON-RR') > '04-9月 -18';
AI 代码解读
    ID RQ
---------- --------------
     1 10-8-18
     2 15-8-18
     3 18-8-18
     4 18-8-19
     5 05-8-18
     6 10-8-18
     7 20-8-18
     8 25-8-18
     9 25-9-18
    11 15-9-18

已选择10行。

SCOTT@vbox66in>

SCOTT@vbox66in>select * from test_riqi where rq > '04-9-18';

    ID RQ
---------- --------------
     4 18-8-19
     9 25-9-18
    11 15-9-18

SCOTT@vbox66in>
AI 代码解读

        从执行结果来看,发现比2018.09.04日期小的也显示出来了,正确的结果应该是下面的三条记录,那么造成这个的原因是什么呢?

②可以看到第一个SQL语句中过滤字段加了to_char函数,to_char将RQ字段转换为了字符类型,字符类型比较大小和日期类型是不一样的,看下字符类型是如何比较的:

SCOTT@vbox66in>create table test_zf(id number,val varchar2(30));
表已创建。
SCOTT@vbox66in>insert into test_zf values(1,'1');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'2');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'123');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'6');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'ABC');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'C');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'F');
SCOTT@vbox66in>select * from test_zf;
    ID VAL
---------- ------------------------------
     1 1
     1 2
     1 123
     1 6
     1 ABC
     1 C
     1 F
已选择7行。

SCOTT@vbox66in>select * from test_zf where val < '3';

    ID VAL
---------- ------------------------------
     1 1
     1 2
     1 123

SCOTT@vbox66in>select * from test_zf where val < 'D';

    ID VAL
---------- ------------------------------
     1 1
     1 2
     1 123
     1 6
     1 ABC
     1 C

已选择6行。

SCOTT@vbox66in>
SCOTT@vbox66in>insert into test_zf values(1,'AC');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'ACF');
已创建 1 行。
SCOTT@vbox66in>insert into test_zf values(1,'AE');
已创建 1 行。
SCOTT@vbox66in>select * from test_zf where val < 'AD';

    ID VAL
---------- ------------------------------
     1 1
     1 2
     1 123
     1 6
     1 ABC
     1 AC
     1 ACF

已选择7行。

SCOTT@vbox66in>
AI 代码解读

        从上述测试可以看到,val字段过滤小于‘3’时,结果123也显示了出来,如果是数字来讲这显然是不正常的。字符类型的比较是将字符转换为ASCII码对应的数值之后进行比较,而且是从左往右进行比较,只要有一个字符符合条件之后就不在进行比较。现在就可以解释上述日期类型比较有差错的问题了,当查询日期大于‘04-9月 -18’的日期时,由于to_char将日期转换为字符,在进行比较时只要RQ这个字段值第一个字符大于0就可以显示出来。

2、日期显示格式为YYYY-MM-DD HH24:MI:SS

        日期显示格式为YYYY-MM-DD HH24:MI:SS则不会出现上述的问题,因为是按照进制的形式增大,所以就是用to_char函数将日期转换为字符串也能查询出正常数据

3、在过滤的条件的字段上加函数会导致查询不走索引,如果有这样的需求可以在相应的字段加函数索引。

相关文章
第三篇:高级 SQL 查询与多表操作
本文深入讲解高级SQL查询技巧,涵盖多表JOIN操作、聚合函数、分组查询、子查询及视图索引等内容。适合已掌握基础SQL的学习者,通过实例解析INNER/LEFT/RIGHT/FULL JOIN用法,以及COUNT/SUM/AVG等聚合函数的应用。同时探讨复杂WHERE条件、子查询嵌套,并介绍视图简化查询与索引优化性能的方法。最后提供实践建议与学习资源,助你提升SQL技能以应对实际数据处理需求。
162 1
【YashanDB知识库】字段加上索引后,SQL查询不到结果
【YashanDB知识库】字段加上索引后,SQL查询不到结果
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
OmniSQL:开源文本到SQL神器!自然语言秒转查询到复杂多表连接等SQL需求
OmniSQL是开源的文本到SQL转换模型,通过创新的数据合成框架生成250万条高质量样本,支持7B/14B/32B三种模型版本,能处理从简单查询到复杂多表连接等各种SQL需求。
370 16
OmniSQL:开源文本到SQL神器!自然语言秒转查询到复杂多表连接等SQL需求
玩转大数据:从零开始掌握SQL查询基础
玩转大数据:从零开始掌握SQL查询基础
205 35
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
SQL为什么不建议执行多表关联查询
本文探讨了SQL中不建议执行多表关联查询的原因,特别是MySQL与PG在多表关联上的区别。MySQL仅支持嵌套循环连接,而不支持排序-合并连接和散列连接,因此在多表(超过3张)关联查询时效率较低。文章还分析了多表关联查询与多次单表查询的效率对比,指出将关联操作放在Service层处理的优势,包括减少数据库计算资源消耗、提高缓存效率、降低锁竞争以及更易于分布式扩展等。最后,通过实例展示了如何分解关联查询以优化性能。
129 0
面试时被这样一个问:”存储MD5值应该用VARCHAR还是用CHAR?
一个5年工作经验的小伙伴,在面试的时候被这样一个问题。说”存储MD5值应该用VARCHAR还是用CHAR“,他一时间不只如何选择,感觉用VARCHAR也可以,用CHAR也行。希望我来帮忙分析一下。
231 0
|
5月前
|
SQL
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
**问题简介:** 客户在使用触发器将表 A 中 varchar(4000 char) 列的数据复制到表 B 时,发现表 B 中的数据出现乱码且与表 A 不一致。此问题影响所有 YashanDB 版本,原因是 YashanDB 在处理触发器场景下的大长度 varchar 数据复制时存在机制错误。为避免该问题,建议将列长度修改为 varchar(2000 char) 或更小。数据正确性无法保证,需谨慎处理。 **验证方法:** 可通过创建表 A 和 B 及相应触发器进行测试。
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
|
4月前
|
SQL
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等