NLS_LANG setting for JDBC thin driver? - oracle

I am using the thin Oracle JDBC driver ver 10.2.0 (ojdbc14.jar). I would like to configure its NLS_LANG setting manually. Is there a way?
Currently it fetches this setting from the VM variable user.language (which is set automatically by setting the current locale, or on startup from the system environment).
This is a problem when the users switch the application locale to a one that is unsupported by the Oracle JDBC driver (e.g. mk_MK). In this case, the next time I fetch a connection I get the following exception:
ORA-00604: error occurred at recursive SQL level 1
ORA-12705: Cannot access NLS data files or invalid environment specified
I can change the locale on the fly just before I fetch the connection and switch back to the user's selected one back and forth, but this seems unelegant and unefficient.

See also: https://serverfault.com/questions/63216/ora-12705-cannot-access-nls-data-files-or-invalid-environment-specified/64536
For me the best response was by FoxyBOA to invoke java app with:
-Duser.country=en -Duser.language=en

The NLS_LANG settings are derived from the java.util.Locale . Therefore, you will need to make a call similar to this before connecting:
Locale.setDefault(Locale.<your locale here>);

I was fighting the same problem and found out that thin jdbc Oracle drivers do not require NLS_LANG or system locale to be specified. But when you connect to non-english databases you are to have orai18n.jar in the classpath.
from Oracle® Database JDBC Developer’s Guide and Reference
Providing Globalization Support
The basic Java Archive (JAR) files,
ojdbc5.jar and ojdbc6.jar, contain all
the necessary classes to provide
complete globalization support for:
Oracle character sets for CHAR,
VARCHAR, LONGVARCHAR, or CLOB data
that is not being retrieved or
inserted as a data member of an Oracle
object or collection type.
CHAR or
VARCHAR data members of object and
collection for the character sets
US7ASCII, WE8DEC, WE8ISO8859P1,
WE8MSWIN1252, and UTF8.
To use any other character sets in
CHAR or VARCHAR data members of
objects or collections, you must
include orai18n.jar in the CLASSPATH
environment variable of your
application.

Invoking java with the following works for me :
-Duser.country=us -Duser.language=en
if "en" for country also causes ORA-12705.

You should use the old Oracle 9.2 JDBC driver that is fully compatible and certified with Oracle 10g. The old driver does not use ALTER SESSION SET NLS_LANGUAGE commands.

Related

OCI JDBC Driver and NLS Settings

We have created a "after logon" trigger to alter the session in order to set the two NLS settings - NLS_SORT and NLS_COMP. NLS_SORT needs to be set to BINARY_CI and NLS_COMP needs to be set to LINGUISTIC. By querying the V$NLS_PARAMETERS view after establishing the connection to verify the values I see that NLS_COMP parameter gets updated but NLS_SORT doesn't.
After researching more I realized that the OCI JDBC driver executes the below query after the connection is established
ALTER SESSION SET NLS_LANGUAGE='AMERICAN' NLS_TERRITORY='AMERICA'
Since NLS_SORT derives its values from NLS_LANGUAGE, NLS_SORT parameter value resets to BINARY instead of BINARY_CI. The NLS_LANGUAGE setting is taken from windows registry.
Does the oci jdbc driver execute these queries to synchronize the NLS settings on the client to that with the database server?
Can the jdbc oci driver be configured to avoid executing the alter session set NLS_LANGUAGE query?
The reason I ask the second question is that it doesn't make sense for application server (e.g glassfish, tomcat, jboss) machine (on which the OCI client is installed) settings to override the database server settings.
I have been wrestling with the exact same problem after introducing a trigger on logon for setting these values.
"The purpose of the NLS_LANGUAGE and NLS_TERRITORY settings are to let the database know locale information. These are derived from the NLS_LANG setting on the client (but can also be changed). These settings allow the database to send data back to the client in the expected format and language." - taken from here
No, it can't be configured to avoid that execution, though it might be a future feature. As it is, it seems the only solution is to have your application always change these parameters after logging in.
It might be of help to know that if you're using the thin connector rather than the OCI-driver and you set an on logon trigger, these values will be set properly after logon. The problem here is with the OCI-driver that will set up these values according to NLS_LANG only after the logon trigger has been executed.
According to chapter 19 Globalization Support from Home / Database / Oracle Database Online Documentation 12c Release 1 (12.1) / Application Development / Database JDBC Developer's Guide:
Starting from Oracle Database 10g, the NLS_LANG variable is no longer
part of the JDBC globalization mechanism. The JDBC driver does not
check NLS environment. So, setting it has no effect.
ALTER SESSION statement which you observed probably comes from the following statement from Globalization Support for JDBC Drivers section of chapter 9 Java Programming in a Global Environment from Oracle9i Database Globalization Support Guide (Release 2 (9.2)):
At database connection time, the JDBC Class Library sets the server
NLS_LANGUAGE and NLS_TERRITORY parameters to correspond to the locale
of the Java VM that runs the JDBC driver. This operation is performed
on the JDBC OCI and JDBC thin drivers only, and ensures that the
server and the Java client communicate in the same language.

How can I set the current schema for DB2 using Hibernate/JDBC?

I used to use currentSchema=MYSCHEMA; in my JDBC URL connection, but the version of DB2 we're using no longer supports that, showing the error 'The "currentSchema" property is not allowed on the target server'. I've tried using hibernate.default_schema, but it's not automatically adding the schema to my table names. I don't want to set the schema on every #Table annotation since I'll need to change it between test and production. Is there another way to set on the connection or via Hibernate?
Update: it must have been a driver version issue. I upgraded to later drivers and currentSchema worked.
With DB2 JDBC type 4 driver (com.ibm.db2.jcc.DB2Driver), I'm using this URL to connect :
jdbc:db2://<HOST>:<PORT>/<DATABASE>:currentSchema=<SCHEMA>;
Source: http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/ad/rjvdsprp.htm
All the properties for the 9.7 (Latest) db are here...
https://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.apdv.java.doc/doc/r0052607.html
use:
currentSchema
Specifies the default schema name that is used to qualify unqualified database objects in dynamically prepared SQL statements. The value of this property sets the value in the CURRENT SCHEMA special register on the database server. The schema name is case-sensitive, and must be specified in uppercase characters.

How to set DB2 ODBC driver locale?

I want to import data from a DB2 database into MS Access via ODBC. The connection is set up and working but decimal values get converted due to some locale issue (German Windows).
234.75 ends up as 23475 in the Access table.
I had the same issue with Oracle but was able to fix it by setting the ODBC drive to US locale. How can I do that with the DB2 ODBC driver?
DB2 v9.5
Do you have the possibility to read some of your field's properties through your ODBC connection? In this case I guess you could find that some of these properties will help you identify field's type, default value, length, etc. It should be then possible for you to incorporate in your import code some conversion instructions for numbers.
Have you tried to change your windows locale settings to US (start/Settings/Control Panel/Regional and language Settings/Regional Settings/customize)?
Even if your windows is german, you can set things such as decimal separator, date, etc to other standards (meaning for example that you can specificaly declare '.' as decimal separator instead of ',' for all windows applications.
When you set an ODBC connection with the linked table manager and you click through all the screens about database name, what credentials to use, there is a checkbox there for "Use regional settings when outputting dates, times, etc... something like that..." Is that checked?
Though this is an old posting some people might benefit from the solution to this issue (which I also encountered). The solution is:
Start the ODBC Administrator
Open the DSN
Open tab page Advanced
Setting Add a line with the following specs:
CLI Parameter: Patch2
Value: 15
This tells the DB2 client to use '.' as a decimal separator in stead of the locale.
Tested on: DB2 V9.7, Access 2010
Source: http://www-01.ibm.com/support/knowledgecenter/#!/SSEPGG_9.7.0/com.ibm.db2.luw.apdv.cli.doc/doc/r0008805.html

how to use different oracle character sets in one application

i'm developing a 32bit Client-Application with Delphi. From this application I need to connect to databases on two different servers. First databse character set ist WE8MSWIN1252, the other server decodes with WE8PC850. Setting the client NLS_LANG parameter to the correct value solves correct sql-query results.
Unfortunately this (the client character-set) seems only to be recognized on applications startup (first connect to oracle). I need to change the client-characterset at runtime. Oracle client seems to store the character set an application used to connect!
beside: I#m using udl-files to setup the connections (Microsoft OLE DB - driver)
what can I do?
You could use ALTER SESSION calls to change the settings at the session level after connecting to the database.
I need to change the
client-characterset at runtime.
Why ? I would have thought what you want at the client end is a character set that is acceptable to the operating environment and end-user.
Pick out a character set such as UTF-8 and let Oracle handle the conversion between the client character set and the two database character sets.

ORA-00604 ORA-12705

I am having this error in my j2ee web application.
java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-12705: Cannot access NLS data files or invalid environment specified
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:145)
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:283)
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:278)
oracle.jdbc.driver.T4CTTIoauthenticate.receiveOauth(T4CTTIoauthenticate.java:785)
oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:376)
oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:441)
oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:839)
java.sql.DriverManager.getConnection(Unknown Source)
java.sql.DriverManager.getConnection(Unknown Source)
org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133)
org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142)
org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85)
org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1353)
org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85)
org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1353)
This project works in my colleagues' PCs... I mean this project works for them but when I asked for their project folder and imported it on my eclipse, when i run it i meet this error. The jar files are already packaged with the project folder.
I also created a simple j2ee project using hibernate but I had the same error.
I tried to ping the DB server and browse it using PL/SQL developer and I don't have any problem with it
Try following:
Check that NLS_LANG setting is correct. On windows it is in registry under \HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE.
Check that Oracle client software is correctly installed.
Check if there are multiple Oracle homes on that computer. In that case, find active one and check if it works.
Test with SQL*Plus if there is one installed. Sql Developer works because it has its own client installation.
Edit:
Regarding drivers, check this site: Oracle Instant Client. There you will find documentation on minimum drivers installation needed for JDBC access to Oracle. I don't know much about that because I use .Net.
Edit 2:
See this question: NLS_LANG setting for JDBC thin driver. There is same error as you have and problem was that default locale for NLS LANG was not defined. Quote:
The NLS_LANG settings are derived from the java.util.Locale . Therefore, you will need to make a call similar to this before connecting:
Locale.setDefault(Locale.<your locale here>);
I figured out that that you could pass that two params to your Java app to resolve the issue:
-Duser.country=en -Duser.language=en
You could configure the values at environment variable level as well (depends from your OS).
I had the same problem. The solution was to add the country and the language to sqldeveloper.conf
Please open the file:
\sqldeveloper\sqldeveloper\bin\sqldeveloper.conf
And add the following:
AddVMOption -Duser.language=en
AddVMOption -Duser.region=us
The above does the trick.
Reference: http://forum.oradba.net/showthread.php?t=423&langid=1
For Windows env, you need to change the System Locale and System Format to English/US.
How to change system locale?
I found solution, I just change the regional and language in my OS (windows 7), make sure it matches with the oracle regional and language.
Oracle JDBC driver implicitly executes following statement after opening new connection:
ALTER SESSION SET NLS_LANGUAGE='language' NLS_TERRITORY='territory'
In our case we had problems with Oracle XE 11g and default language/territory mappings embedded into JDBC driver: 'ru' locale was mapped to 'CIS' territory which is supported only by Oracle EE, but Oracle XE had 'RUSSIA' territory only.
Here is the way we fixed this:
-Doracle.jdbc.territoryMap="ru=RUSSIA;RU=RUSSIA"
There is option for NLS_LANGUAGE(we had no problems with defaults):
-Doracle.jdbc.languageMap="ru=RUSSIAN;RU=RUSSIAN"
Fixed: constant ru=RUSSIAN taken from class oracle.sql.converter.CharacterSetMetaData of java jdbc driver.
If you are compiling with intelljIDE I advise you add following options in VMoptions found in configurations model
AddVMOption -Duser.region=us.
First execute query:
select userenv('LANGUAGE') from dual;`
This will give oracle regional and language. Change the regional and language in OS, both should match.
check the JAVA_HOME system variable and verify that it is the same version you are using in your projects and programs
Changing the region settings and language of my machine helped to get away with this.
I changed region to United States and English (United States) as language.
If you are running a spring application just add Locale.setDefault(Locale.ENGLISH); at main class.
public static void main(String[] args) throws Exception
{
Locale.setDefault(Locale.ENGLISH);
SpringApplication.run(ApplicationName.class, args);
}

Resources