热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

探索Oracle自动类型转换(下)

点击上方“IT那活儿”公众号,关注后了解更多内容,不管IT什么活儿,干就完了!!!
点击上方“IT那活儿”公众号,关注后了解更多内容,不管IT什么活儿,干就完了!!!

自动类型转换常见错误

下面选择一个在PL/SQL程序中的常犯错误说明自动类型转换容易导致的问题,特别是DATE类型自动转换导致问题,希望给予读者一些警示,不要使用自动类型转换,上篇文章已经说了这么多缺点,这里就不重复叙述了。
请看例子,为了简单说明只建了表未插入数据,有兴趣的可以自己插入数据测试一下:

DINGJUN123>DROP TABLE t;

表已删除。

DINGJUN123>
CREATE TABLE t
2 (id NUMBER,
3 done_date DATE
4 );

表已创建。

--建立过程的时候并没有报错,我加了打印语句,方便下面看错误原因:

DINGJUN123>CREATE OR REPLACE PROCEDURE
2 sp_t (i_tabname VARCHAR2,i_date DATE,o_count OUT NUMBER)
3 /***********************************************************************
4 ||desc:根据传入的表名和日期查询大于此日期的记录数
5 ||此函数应用的表都有相同的统计日期列done_date
6 ************************************************************************/
7 AS
8 v_sql VARCHAR2(1000);
9 BEGIN
10 v_sql := 'SELECT COUNT(*) FROM '
11 || i_tabname || ' WHERE done_date> '
12 || i_date;
13 DBMS_OUTPUT.PUT_LINE(v_sql);
14 EXECUTE IMMEDIATE v_sql INTO o_count;
15 END;
16 /

过程已创建。

DINGJUN123>VAR o_count NUMBER
DINGJUN123>SET SERVEROUTPUT ON
DINGJUN123>EXEC sp_t ('t',SYSDATE,:o_count);
SELECT COUNT(*) FROM t WHERE done_date> 12-6月 -21
BEGIN sp_t ('t', SYSDATE,:o_count); END;

*

第 1 行出现错误:

ORA-00933: SQL 命令未正确结束
ORA-06512: 在 "DINGJUN123.SP_T", line 14
ORA-06512: 在 line 1
看到错误了吧,日期类型发生了类型转换,根据NLS_DATE_FORMAT和NLS_DATE_LANGUAGE参数设置自动变为字符串了,而且这个字符串还不是Oracle中的表示的字符串,看到了没有,是12-6月 -21而不是'12-6月 -21',很多人经常拼凑字符串的时候少了引号,当然这里拼凑加上引号是可以的,那么就有多次自动类型转换,将v_sql改为:

v_sql := 'SELECT COUNT(*) FROM '
||i_tabname || ' WHERE done_date> '
||chr(39)
||i_date
||chr(39);

上面的chr(39)就是单引号,因为在字符串中表示一个单引号比较麻烦,所以用chr(39)代替。然后重新编译过程并测试:

DINGJUN123>ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD';
会话已更改。

DINGJUN123>
EXEC sp_t ('t', SYSDATE,:o_count);
SELECT COUNT(*) FROM t WHERE done_date> '2021-06-12'

PL/SQL 过程已成功完成。

DINGJUN123>
PRINT o_count

O_COUNT
----------
0

首先SYSDATE转为字符串,将SQL拼凑好,结果就是上面打印出的语句,然后执行SQL,右边的'2021-06-12'遇到了左值是DATE类型,又进过一次类型转换,将字符串转为DATE类型,转换的过程很复杂。这种拼凑SQL的方式也是不可取的
自动类型转换特别是在日期类型的处理过程中,经常发生类似的错误,如果有很好的编码习惯,这种错误是完全可以避免的,类似这样的查询,不应该使用常量直接拼凑,一般应使用绑定变量的方式:

DINGJUN123>CREATE OR REPLACE PROCEDURE
2 sp_t (i_tabname VARCHAR2,i_date DATE,o_count OUT NUMBER)
3 /***********************************************************************
4 ||desc:根据传入的表名和日期查询大于此日期的记录数
5 ||此函数所有的表都有共同的统计日期列done_date
6 ************************************************************************/
7 AS
8 v_sql VARCHAR2(1000);
9 BEGIN
10 v_sql := 'SELECT COUNT(*) FROM '
11 || i_tabname || ' WHERE done_date> : i_date ';
12 DBMS_OUTPUT.PUT_LINE(v_sql);
13 EXECUTE IMMEDIATE v_sql INTO o_count
14 USING i_date;
15 END;
16 /

过程已创建。

DINGJUN123>EXEC sp_t ('t',sysdate,:o_count);
SELECT COUNT(*) FROM t WHERE done_date> : i_date

PL/SQL 过程已成功完成。

DINGJUN123>PRINT o_count
O_COUNT
----------

0


本文作者:丁 俊(上海新炬王翦团队)

本文来源:“IT那活儿”公众号


推荐阅读
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了C函数ispunct()的用法及示例代码。ispunct()函数用于检查传递的字符是否是标点符号,如果是标点符号则返回非零值,否则返回零。示例代码演示了如何使用ispunct()函数来判断字符是否为标点符号。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 开发笔记:select from具体执行相关知识介绍及案例分析
    本文由编程笔记小编整理,主要介绍了select from具体执行相关的知识,包括数据插入、查询最小rowID、查询每个重复名字的最小rowID、删除重复数据等操作,并提供了案例分析。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 摘要: 在测试数据中,生成中文姓名是一个常见的需求。本文介绍了使用C#编写的随机生成中文姓名的方法,并分享了相关代码。作者欢迎读者提出意见和建议。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
author-avatar
茶茶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有