半瓶内容

 results 1 - 1 of about 1 for SQL语句的日期格式和nls_date_format参数. (0.320 seconds) 

SQL语句的日期格式和nls_date_format参数

前段时间把一个在Linux 平台运行的应用程序部署一套到windows平台上,是java开发的基于oracle10g的程序,部署完成后,发现有个写入操作会报错,而后台跟踪到的SQL是插入日期时侯出现的问题。

insert into t ( fromtime ) values ( '2009-4-15' )

其中的fromtime是date 类型,而SQL中并没有对字符串做to_date转化。程序不大好修改,只能在环境变量等参数配置上下手。而奇怪的是这样的SQL在原来的Linux 平台上能运行的很好,说明是和环境问题是有关的。

首先修改了oracle的nls_date_format参数,原来是空的,改为yyyy-mm-dd hh24:mi:Ss,用sqlplus连到服务器测试SQL能执行,但是java程序还是报错,看来得改客户端的nls_date_format设置,老熊说有些jdbc驱动可以采用设置数据库的nls_data_format方式来解决,因为这种驱动连接上后自动将会话的这个设为跟数据库一样的。修改windows系统的环境变量仍然不行,看来java程序可以不从操作系统来读变量。以下是测试过程:

SQL> create table t1 (mydate varchar2(20));

Table created.

SQL> insert into t1 mydate values (2010-10-10);

1 row created.

SQL> alter table t1 modify mydate date;

Table altered.

SQL>
SQL> desc t1;
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
MYDATE                                             DATE

SQL> insert into t1 mydate values ('2010-10-10');
insert into t1 mydate values ('2010-10-10')
*
ERROR at line 1:
ORA-01861: literal does not match format string

SQL> show parameter nls_date

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
nls_date_format                      string
nls_date_language                    string

SQL> alter system set nls_date_format='yyyy-mm-dd hh24:mi:ss';
alter system set nls_date_format='yyyy-mm-dd hh24:mi:ss'
*
ERROR at line 1:
ORA-02096: specified initialization parameter is not modifiable with this
option

SQL> alter system set nls_date_format='yyyy-mm-dd hh24:mi:ss' scope=spfile;

System altered.

SQL>
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 2147483648 bytes
Fixed Size                  2022144 bytes
Variable Size             285213952 bytes
Database Buffers         1845493760 bytes
Redo Buffers               14753792 bytes
Database mounted.
Database opened.
SQL> show parameter nls_date_format

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
nls_date_format                      string      yyyy-mm-dd hh24:mi:ss

SQL> insert into t1 mydate values ('2010-10-10');

1 row created.

SQL> commit;

Commit complete.

最后尝试在程序使用的oracle用户登录的时侯修改当前session的nls_date_format,通过触发器来实现

create or replace trigger tri_logon_nlsformat
after logon
ON DATABASE
when (USER='BANPING')
begin
execute immediate 'alter session set nls_date_format = ''YYYY-MM-DD'' ';
end;

这样用户通过应用程序每次连接到数据库的时侯,就修改当前session的nls_date_format,应用程序不再报错,不过这只是一个丑陋的解决办法,根本的还需要从修改程序入手。


Reader's Comments

  1. |

    Language and Territory

    The Thin driver obtains language and territory settings (NLS_LANGUAGE and NLS_TERRITORY) from the Java locale in the JVM user.language property. The date format (NLS_DATE_FORMAT) is set according to the territory setting.

  2. |

    谢谢weblogicfans指点,有空测试一下。

  3. |

    我一直看你的BLOG,非常不错。

    我也是根据文档推测,我数据库水平很一般也没条件做测试,你可以认为是另外一个解决的途径,成不成功我也不敢保证。

    上面的E文来自oracle官方的JDBC guide。

    简单的说,如果不指定java的user.language和user.region变量,则java使用系统的LOCALE来算出当前的user.language、user.region。

    中文windows,可以简单的认为是zh_CN

    user.language、user.region可以自己指定,比如linux下面locale是en_US的时候java启动参数加上:
    -Duser.language=zh -Duser.region=CN
    从系统看,locale是en_US,但是java内部认为locale是zh_CN

    而NLS_DATE_FORMAT的格式与user.language有直接关系。

Leave a Comment