解决ora-01861文字与格式字符串不匹配

来源:互联网 发布:sql 循环select结果集 编辑:程序博客网 时间:2024/07/17 21:32

症状:c/s程序本来运行正常,一次重装系统,重装oracle客户端后,insert日期格式数据,出现题目中错误。

    解决办法:

    Oracle时间格式讨论

    在网上看见不少oracle新学者对oracle的时间格式很烦,经常是设计了一个带时间字段的表之后,向表插入数据失败。回想起自己刚开始学习oracle时,也对这个时间格式摸不着头脑,虽然是小小的问题,高手们不屑于讨论,但对初学者来讲,这也是一个不大不小的坎,没找到门路的话, 可能几天都过不去,其实就是一层窗户纸,没什么难的。这里做一个简单的小结,因水平有限,请高手补充指正。

    1 oracle对时间格式的数据存贮

    oracle数据库中存放时间格式的数据,是以oracle特定的格式存贮的,占7个字节,与查询时显示的时间格式无关,具体哪个字节表示什么,我不太清楚,请高手补充。存贮的时间包括年月日时分秒,最小精度为秒,不存贮秒以下的时间单位。因此在一些前台支持毫秒级的程序(如PB客户端程序)连接到oracle数据库时应注意这点。查询时显示的时间格式,由会话环境决定,或者由用户定义,与数据库无关。

    2 oracle时间显示形式

    通常,客户端与数据库建立起连接后,oracle就会给一个缺省的时间格式数据的显示形式,与所使用的字符集有关。一般显示年月日,而不显示时分秒。例如,使用us7ascii字符集(或者是其他的英语字符集)时,缺省的时间格式显示为:28-Jan-2003,而使用zhs16gbk字符集(或其他中文字符集)时时间格式缺省显示为:2003-1月-28.向表中插入数据时,如果不使用转换函数,则时间字段的格式必须遵从会话环境的时间格式,否则不能插入。查看当前会话的时间格式,可以使用以下的SQL语句:SQL> select sysdate from dual;(只能按照此语句的结果,才能插入数据)

    3 向oracle表中插入时间格式的数据

    向oracle表插入时间格式的数据是一个相对来讲比较麻烦的事情,要么你严格遵从当前会话的时间格式书写你的时间值,要么使用转换函数自定义时间数据的格式。有两个与时间相关的转换函数:to_char 和 to_date .to_char(时间值,时间格式)函数将时间值转换为字符串形式,通常在查询中使用;to_date(字符串,时间格式)则把格式字符串转换时间值,通常在insert 语句中使用。(呵呵,程序中没这样做,所以出错)在日期格式中,各种日期格式分量这里不作详细的讨论,请查oracle帮助文档中这两个函数的用法,或者查一查PL/SQL编程的书,讲得很详细的。

    4 如何修改会话中的日期格式

    修改当前会话中的日期格式据说有三种办法,我只做过前两种办法的试验,修改glogin.sql文件的办法我没有试过,不知道是不是真的能行。下面一一解说。

    (1) 在sql*plus中修改当前会话的日期格式SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';将当前会话的时间格式修改为这种格式: 2003-01-28 15:23:38,即四位年-两位月-两位日,空格,24小时的制的小时:分钟:秒。

    这种修改方法,只对当前会话有效。注意,是对当前会话,而不是当前的sql*plus窗口。即如果你这样修改之后,又使用connect命令以其他用户连接到数据库或者是连接到其他的数据库,则这个日期格式就失效了,又恢复到缺省的日期格式。

    (2) 修改注册表(只对windows系统)

    在注册表hkey_local_machinesoftwareoraclehome0主键中增加一个字串(8i版本,9i也可以),字串名为nls_date_format,字串的值为你希望定义的时间格式,如: yyyy-mm-dd hh24:mi:ss ,然后重新启动sql*plus.这种修改方法,对sql*plus窗口有效,即不论你打开多少个sql*plus窗口,缺省的都是这种时间格式。修改服务器端的注册表无效,只有修改客户端的注册表才有效。

    unix系统下有没有这类似的方法,我不知道,我不会用unix或者是linux系统。

    (3) 修改$oracle_homesqlplusadmin目录中glogin.sql文件这种方法我没有试过,不敢乱说,以免误导大家。请了解这种方法的高手来指教。

    5 日期格式的优先级

    如果在一个具体的环境中,既修改了注册表,又使用alter session命令修改了当前会话,那么哪一种修改方法有效呢?alter session命令有效,它的优先级是最高的。即不管当前的客户端环境是什么样的,注册表修改成什么样子了,只要你使用了alter session命令来修改了时间格式,那么就以你修改后的时间格式为准。

    因此,如果直接使用sql*plus交互式查询或插入时间格式的数据,两种方法都可以用。如果使用sql文件来进行批量的插入或者是定时执行,最好在使用时间数据前使用alter session命令来修改会话,以保证这个sql语句的正常运行与环境无关。同样的,如果是前台的客户端程序中需要使用到时间格式的数据,最好也在使用之前修改会话,或者使用to_char或to_date函数进行转换(强烈推荐使用转换函数),以保证程序运行与环境无关。

    小结:

    oracle数据库中有关时间类型的数据,定义了很多函数,特别是关于时间数据的计算,非常方便,当然,方便的前提是你对oracle的时间函数比较熟悉。在这里我有时候看到有些人存贮时间类型的数据时使用字符串类型的字段,我强烈的反对这种做法,不论是从系统的开销,还是从时间数据的计算来讲,或者是取这个数据中的某一个子数据,比如取时间中的月,取时间中的星期等等,都不如直接存贮为时间类型的数据来得方便。只要熟悉了oracle关于时间的函数,我相信大家会喜欢上oracle时间类型的数据的,非常灵活,功能强大,几乎可以做你所能想到的关于时间的一切事情——就看你对oracle的时间函数掌握程度了以上在windows 2000 + oracle 805版本测试通过,不对之处,请高手指正。

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1497362

最后检查JRE所需版本,最新版本要求是1.1.8 

# java -version 
java version "1.5.0_07" 
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b03) 
Java HotSpot(TM) Server VM (build 1.5.0_07-b03, mixed mode) 

满足安装Oracle的最小要求后,就可以使用root用户来设置系统参数并创建Oracle用户了。 

在/etc/system文件后面添加下面内容: 


set shmsys:shminfo_shmmax=8589934592set shmsys:shminfo_shmmin=1setshmsys:shminfo_shmmni=100set shmsys:shminfo_shmseg=10setsemsys:seminfo_semmni=100set semsys:seminfo_semmsl=256setsemsys:seminfo_semmns=1024
这是对系统内存参数的调整,修改完毕后重新操作系统。 

# groupadd dba 
# groupadd oinstall 
# mkdir /export/home/oracle 
# useradd -g oinstall -G dba -d /export/home/oracle oracle 
# passwd oracle 

建立组和用户后,为oracle设置安装软件的路径和权限: 

# chown -R oracle:oinstall /export/home/oracle 
# chown -R oracle:oinstall /ora9i 

下面root用户的工作结束,切换到oracle用户: 

# su - oracle 

$ vi .profile 

编辑.prifle文件,添加下列内容: 

ORACLE_SID=testexport ORACLE_SIDORACLE_BASE=/ora9i/oracle/ora92export ORACLE_BASEORACLE_HOME=$ORACLE_BASE/product/9.2export ORACLE_HOMEPATH=$PATH:$ORACLE_HOME/bin:/usr/bin:/usr/ccs/bin:/etc:/usr/openwin/binexport PATHNLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"export NLS_LANGDISPLAY=172.25.6.201:1.0export DISPLAY
由于使用XManager,因此设置DISPLAY为IP:1.0。然后建立所需安装路径: 

$ mkdir -p /ora9i/oracle/ora92/product/9.2使用XManager用root登陆,执行# xhost +access control disabled, clients can connect from any host# su - oracle


 

进入disk1目录,执行./runInstaller,进入Oracle的安装图形界面: 

在UNIX Group Name的地方填入刚才建立oinstall,点击NEXT,然后以root执行/tmp/orainstRoot.sh脚本。 

再安装过程中选择产品的时候把简体中文语言Simplified Chinese选择上,剩下的一路NEXT就可以了。

当软件安装结束后,会提示以root执行$ORACLE_HOME目录下的root.sh脚本,执行后,点击ok,Oracle软件部分就安装完成了。 

配置TNSNAME和LISTENER步骤很简单,就不描述了。 

下面是建立数据库,这个过程也没有什么好说的,整个过程也没有什么值得一提的。 

  虽然过程本身很简单,但是我还是碰到了一点麻烦。用dbca生成脚本的时候,dbca本身的bug,在修改文件的大小时,Oracle没有在原有数据文件上修改大小,而是新增了一条数据文件。而我生成脚本的时候也没有注意。等到建立数据库的时候报错才发现问题。 

  由于Solaris10系统是第一次使用,首先怀疑到操作系统对数据库支持有问题。不过一般情况下,出错都发生在安装过程中,数据库建立一般很少出错。检查alert脚本,根据错误信息描述,感觉似乎是空间不足造成的。可是目标目录明明有足够的空间,于是又把怀疑的目光放到操作系统的限制上,结果在尝试修改建库脚本中数据文件的大小时才发现,dbca为SYSTEM表空间添加了5M的数据文件。解决这个问题后,建库过程顺利完成。 

   其实,如果是一个熟悉的操作系统,那么可能定位问题会更快一些。当碰到问题的时候,总是习惯于将怀疑的对象定位于不熟悉的部分,很多时候确实是由于不熟悉的部分引发的错误,但是有的时候却容易误入歧途,本来很容易定位的问题,需要绕过一个很大的圈子才找到错误的原因