NLS_LANG Client Settings and JDBC Drivers (文档 ID 115001.1)
The purpose of this article is to summarize ways to access an Oracle database from a client when a Java-based application is used, as well as to clarify NLS_LANG setting question.
Oracle Support Analysts, Database Administrators.
Users can write a Java application using JDBC or SQLJ programs with embedded SQL statements to access an Oracle database. The following are Oracle RDBMS Java components that provide NLS support:
This article will cover only the JDBC Driver as a means to access an Oracle RDBMS database.
Oracle JDBC drivers allow users to retrieve data from or insert data into a database in any character set that Oracle supports. Please keep in in mind that the target character set on the client is always UCS2 / UTF16 because Java is based on UCS2 / UTF16 type of Unicode. Therefore character set conversion will take place to convert data from the database character set to UCS2 / UTF16. This applies to CHAR, LONG, CLOB, and VARCHAR2 data types; RAW and BLOB data are not converted.
Since the Java-client side is using Unicode, we strongly recommend to use an Unicode (AL32)UTF8 database.
The techniques that Oracle's drivers use to perform character set conversion for Java applications depend on the character set the database uses.
To check the database character set, run the following SQL command:
SQL> select value from nls_database_parameters
2 where parameter = 'NLS_CHARACTERSET';
Example 1:
The database uses the US7ASCII or WE8ISO8859P1 character set. In this case, the driver converts the data directly from the database character set to UCS2 / UTF16 , which is used in Java applications.
Example 2:
The database uses a non-US7ASCII or non-WE8ISO8859P1 character set (like JA16SJIS, JA16EUC, ZHT16BIG5...). The driver converts the data, first to UTF8, then to UCS2 / UTF16.
Example 3:
The database uses a AL32(UTF8) character set. The driver converts the data from UTF8 to UCS2 / UTF16. This is a very "cheap" operation with extremely low memory and cpu overhead.
When character data is inserted into or retrieved from the database, Oracle JDBC drivers perform character set conversions as appropriate. The drivers convert Unicode characters used by Java clients to Oracle database character set characters, and vice versa.
When used in a web ( HTTP ) environment make sure that your web env is correct per: NLS_LANG and webservers explained.
When using JDBC to insert data in N-types (NCHAR,NVARCHAR2,NCLOB) please:
You have 2 kinds of JDBC: "Thick" and "Thin"
Thick JDBC
A "Thick JDBC" connection is using this syntax: "jdbc:oracle:oci8:@....."
When Java application uses 9i or lower Thick JDBC to communicate with the Oracle database, NLS_LANG environment variable needs to be set on the server where the Thick JDBC driver is installed.
NLS_LANG needs to be set to the characterset used in the web application or (for non-web java applications) the terminal character set.
Examples:
American_America.WE8MSWIN1252
"English_United Kingdom.UTF8"
9i Thick JDBC (=OCI) driver will make use of the NLS_LANG to determine the how to convert characters. NOT defining the NLS_LANG will make this to use the default US7ASCII setting, any non-ASCII data from /to the database will be lost.
You don't need to specify anything to your Java code for JDBC to pick up the NLS_LANG.
From 10g onwards the Thick JDBC driver is ignoring the NLS_LANG and uses Language, Territory and characterset settings from the JVM locale.
In 11g the property -Doracle.jdbc.ociNlsLangBackwardCompatible=true is settable on the command. If set it causes JDBC to get the characterset from NLS_LANG instead of getting the client characterset id from the locale.
Language and territory are taken from the locale regardless of the property though.
Thin JDBC
A JDBC Thin driver ("jdbc:oracle:thin:@.....") is not using the NLS_LANG.
The Oracle Thin driver supports the following character sets trough basic zip/jar files (classes111.zip, classes111.jar, classes12.zip and classes12.jar, ojdbc14.jar) they contain all the necessary classes to provide complete NLS support for:
If your database use a other character set (WE8ISO8859P15,WE8MSWIN1252, EE8MSWIN1250,...) you must include nls_charsetxx.zip/nls_charsetxx.jar in your CLASSPATH.
If this file is not in your CLASSPATH, you will see the following exception:
java.sql.SQLException: Non supported character set: oracle-character-set-178
when connecting to a WE8MSWIN1252 database.
The "oracle-character-set-178" may be different depending on the characterset of the database you try to connect to.
Connecting to a WE8ISO8859P15 db will return "oracle-character-set-46" for example.
Please do not try to put multiple versions of the Oracle JDBC drivers in your CLASSPATH.
On Windows clients:
See the Readme.txt in [ORACLE_HOME]\jdbc for more information.
When using an WE8MSWIN1252 database please be aware of:
Bug:4659157 NLS: ORA-942 SELECT TABLE WITH LEADING EURO SIGN CHAR IN WE8MSWIN1252 D/B
Fixed-Releases: 10.2.0.4, 11.1.0.6 , 10.2.0.3.6 windows patch set bundle
Details:Some WE8MSWIN1252 characters are not converted properly by the JDBC Thin driver.
Character data making a round trip from the Java Unicode character set to the database character set and back to Java can suffer some loss of information. This happens when multiple Unicode characters are mapped to a single character in the database character set. An example would be the Unicode full-width tilde character (0xFF5E) and its mapping to Oracle's JA16SJIS database character set. The round trip conversion for this Unicode character results in the Unicode character 0x301C, which is a wave dash (a character commonly used in Japan to indicate range), not a tilde. This issue is not a bug in Oracle's JDBC, but rather is an unfortunate side effect of the ambiguity in character mapping specification on different operating systems. Fortunately, this problem affects only a small number of characters in a small number of Oracle character sets such as JA16SJIS, JA16EUC, ZHT16BIG5, and KO16KS5601. The workaround is to avoid making a full round-trip with these characters by simply using a (AL32)UTF8 database.
JDBC (both thick and thin) will use the JVM locale to define NLS_LANGUAGE and NLS_TERRITORY (= NLS_SESSION_PARAMETERS).
This is done by sending "alter session set NLS_.....".
By default, the JVM uses the current locale as defined by the OS. To bypass this configuration, you specify on the command line the locale to be used:
java -Duser.language=en -Duser.region=US MyApplication
Note that there are some bugs with this: http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4152725 , fixed in Java 1.4
Note that there are some problems with the OJVM (Oracle Java Virtual Machine) and JDBC when using a user defined characterset in 10.2.0.3 and lower.
You will see errors like:
ORA-29532: Java call terminated by uncaught Java exception: java.sql.SQLException: Character Set Not Supported !!
If you use a user defined characterset on 10.2.0.3 then you need also to apply patch 5086162, patch 5465998 and patch 6731468 installed for a complete client/server fix.
11.1.0.6 (and higher) and 10.2.0.4 (and higher) include the fix for bug 5086162 and bug 5465998.
the fix for bug 6731468 is only needed on 10.2.0.3
11.1.0.6 and 10.2.0.4 also include this trough bug 5465998
See the Globalization manual on how generate a custom characterset for JDBC with Ginstall.
NOTE:251044.1 - How To Set a NLS Session Parameter At Database Or Schema Level For All Connections?
NOTE:264157.1 - The Correct NLS_LANG Setting in Unix Environments
NOTE:227330.1 - Character Sets & Conversion - Frequently Asked Questions
NOTE:241047.1 - The Priority of NLS Parameters Explained (Where To Define NLS Parameters)
NOTE:229786.1 - NLS_LANG and webservers explained.
BUG:3938420 - TRIGGER IS NOT FIRED WHEN USING THE JDBC OCI DRIVER
BUG:3967004 - EXPOSE TO OCI THE NLS ATTRIBUTES SET DURING CONNECT
BUG:7121190 - JDBC OCI OVERWRITES NLS_SORT SETTINGS DONE BY LOGON TRIGGER
NOTE:158577.1 - NLS_LANG Explained (How does Client-Server Character Conversion Work?)
NOTE:179133.1 - The Correct NLS_LANG in a Microsoft Windows Environment