本文测试所用的Oracle数据库的NLS信息如下
- NLS_LANGUAGE
AMERICAN
- NLS_CHARACTERSET
WE8ISO8859P1
- NLS_NCHAR_CHARACTERSET
UTF8
数据库的表字段选用了NVARCHAR2。
CREATE TABLE UTF8TEST ( LABEL NVARCHAR2(128) );
使用的Oracle客户端是Oracle SQL Developer,这个是Oracle自家出的基于Java的客户端,默认对于多语言的select操作支持比较好,可以直接选出UTF8的数据。但是如果insert或是update的话,还是产生了乱码数据。
INSERT INTO UTF8TEST VALUES ('中文测试'); SELECT * FROM UTF8TEST; ------ LABEL ------- ¿¿¿¿
如果用java/groovy程序,也会产生同样的乱码。用的JDBC Driver是ojdbc14.jar
def db = [ url:'jdbc:oracle:thin:@XXX', user:'XXX', password:'XXX', driver:'oracle.jdbc.driver.OracleDriver'] def sql = Sql.newInstance(db.url, db.user, db.password, db.driver) sql.execute("INSERT INTO UTF8TEST VALUES ('中文测试')") sql.close()
解决的方案,在运行程序的时候加入JVM的参数
-Doracle.jdbc.defaultNChar=true -Doracle.jdbc.convertNcharLiterals=true
Oracle的文档中有如下的说法:
引用
By default, the oracle.jdbc.OraclePreparedStatement interface treats the data type of all the columns in the same way as they are encoded in the database character set. However, since Oracle Database 10g, if you set the value of oracle.jdbc.defaultNChar system property to true, then JDBC treats all character columns as being national-language.
意思是说默认的话,程序jdbc用的是char的映射,只有当设置了JVM System property后,可以默认映射成NCHAR, NVARCHAR, NCLOB。
oracle.jdbc.convertNcharLiterals这个配置可以,用这如下的方法来操作
INSERT INTO UTF8TEST VALUES (N'中文测试');