Oracle NLS_SORT not working on system level - oracle

I am using oracle 11g r2, and trying to configure DB to sort order using linguistic sort.
I did
alter system set NLS_SORT='RUSSIAN' SCOPE=SPFILE;
alter system set NLS_COMP='LINUGUISTIC' SCOPE=SPFILE;
after i've restarter oracle i checked these params:
show parameters NLS_SORT;
show parameters NLS_COMP;
it show me the right values.
But when I make sort
select name from test order by name;
it show me results in not correct order, ie digits first, then letters.
but if i will do
alter session set nls_sort='RUSSIAN';
alter session set nls_comp='LINGUISTIC';
select name from test order by name;
it show me the right order.
anyone know why sysem changes not showing me right results ?

The priority for globalisation settings is shown in the documentation. You're setting priority 4 in that list, 'Specified in the initialization parameter file'. You are not setting priority 1 ('Explicitly set in SQL functions') and you get the results you want when you do set priority 2 ('Set by an ALTER SESSION statement'). By a process of elimination that indicates that your 'not correct' order is being influenced by priority 3, 'Set as an environment variable'.
You can check the values actually being used by your session with select * from nls_session_parameters.
The NLS_SORT environment variable is probably not being set directly; I suspect it's being derived from NLS_LANGUAGE, which is derived from NLS_LANG. If you aren't explicitly setting that in your operating system environment then the client will set it based on the operating system locale, generally, though the exact client you use may make a significant difference. You might need to explicitly set an NLS_COMP environment variable, if the database default for that is really being overridden.
SQL Developer, for example, allows you to specify the NLS settings in the preferences (accessed from Tools->Preferences->Database->NLS); the defaults appear to be based on operating system settings, in Windows anyway. For SQL*Plus you'd need to set operating system environment variables.
This also means that if you get it working in one place - the queries give the right order when run from SQL Developer, say - they might not work when used elsewhere, say over JDBC which has its own locale settings. Just something to watch out for.
A brute-force approach might be to add the alter session commands to a login trigger, but that doesn't sound ideal as it just masks the environment configuration.

You can set NLS parameters at different levels
As initialization parameters on the instance/server.
SQL> alter system set V$NLS_PARAMETER = 'XXX' scope = both;
As environment variables on the client.
% setenv NLS_SORT FRENCH
As ALTER SESSION parameters.
SQL> ALTER SESSION SET V$NLS_PARAMETER = = 'XXX'
Any setting overrides the setting on a higher level. So setting it server side does not guarantee that the setting is used by all clients connecting.
If you want to make sure it is set for every client connecting use a logon trigger. Even then a user can explicitly override the 'default' setting

You've got a typo in your second "ALTER SYSTEM" command (LINUGUISTIC instead of LINGUISTIC).
If your real command doesn't contain this error, I'd check whether your client sets the NLS session parameters to something else.

Regardless of the system settings, I would make every effort to ensure that your applications completely specify the NLS environment that they require. It's much more robust, particularly when you need to point the application code at different environments that may be newly setup, or shared with other systems.
In fact, I'd go as far as to say that you might be better not using setting system-level environment settings.

Related

How do I change the default NLS parameters for date format through Toad?

I have a NLS date format as DD-MON-RR. This gives me the underlying date format as YY while I want to change it to YYYY. I tried using the following query and it ran successfully
DECLARE
v_date DATE := sysdate;
BEGIN
DBMS_OUTPUT.put_line(TO_CHAR(v_date, 'MM/DD/YYYY'));
END;
But that didn't change the default format.
for some context, I am trying to import data from Oracle to Tableau. Unfortunately when I try to export a crosstab from Tableau server it looks at the underlying data rather than whats on the view. This causes the date that I have as 25-Jun-2017 to change to 25-Jun-17 in the excel.
The only workaround I have been able to understand is to change the default format of the underlying/source data which in this case is Oracle DB.
I am using TOAD and am trying to understand how can I change it to possibly DD/MON/RRRR format or something similar with 4 digits in the year column.
Any workaround is also appreciated
As already given in other answers you can set NLS_DATE_FORMAT by ALTER SESSION.
In order to set it only for you local PC, open Registry Editor and navigate to HKLM\SOFTWARE\Wow6432Node\ORACLE\KEY_%ORACLE_HOME_NAME%, resp. HKLM\SOFTWARE\ORACLE\KEY_%ORACLE_HOME_NAME%.
There you can add a String Value NLS_DATE_FORMAT, for example:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient11g_home1]
"NLS_TIMESTAMP_FORMAT"="YYYY-MM-DD HH24:MI:SSfmXFF3"
"NLS_TIMESTAMP_TZ_FORMAT"="YYYY-MM-DD HH24:MI:SSfmXFF3 fmTZH:TZM"
"NLS_DATE_FORMAT"="YYYY-MM-DD HH24:MI:SS"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_OraClient11g_home1]
"NLS_TIMESTAMP_FORMAT"="YYYY-MM-DD HH24:MI:SSfmXFF3"
"NLS_TIMESTAMP_TZ_FORMAT"="YYYY-MM-DD HH24:MI:SSfmXFF3 fmTZH:TZM"
"NLS_DATE_FORMAT"="YYYY-MM-DD HH24:MI:SS"
You can set NLS_DATE_FORMAT also as an Environment Variable in Windows Settings.
alter session set nls_date_format='DD/MON/RRRR' programmatically in the application or
CREATE OR REPLACE TRIGGER trg_after_logon AFTER LOGON ON DATABASE
BEGIN
execute immediate 'alter session set NLS_DATE_FORMAT=''DD/MON/RRRR''';
END;
in system or sys schema.
Alternatively, you may use
alter system set NLS_DATE_FORMAT='DD/MON/RRRR' scope = both
provided you're in system or sys, again.
Manage your date format masking using the most reasonable approach
First of all, I agree with Alex regarding using to_char. This would be my first choice for modifying date masks for specific requirements.
In Toad on an ad hoc basis, you could just invoke the alter session command as needed:
ALTER SESSION SET nls_date_format='DD/MON/RRRR';
If you are partial to a specific date format mask (and you see yourself often issuing the command, ALTER SESSION SET NLS...) then perhaps you might want to consider changing your user login settings.
If you just modify your specific user preference login file, login.sql (see here ), your session will adhere to the date format mask of your choosing at the beginning of your session. I am partial to creating the environment variable, SQLPATH, and placing my login script there.
Toad will honor your login.sql file settings (e.g. see this post).
Since this is driven by specific requirements or personal preferences, I would never think of modifying this from default at the site level.

Compilation converts utf-8 characters to question mark in PLSQL developer

I am using PLSQL developer to work with oracle db. When I compile a view which stores code like this:
select 'xidmət' as service from dual
the 'ə' character in the string becomes '?' character.
I think it's some oracle or plsql developer configuration problem, but I don't know what.What do you think the problem is?
First, check what your character set is using this:
select value from nls_database_parameters where parameter='NLS_CHARACTERSET';
Then set your NLS_LANG environment variable to AMERICAN_AMERICA.CHARSET where CHARSET is the value found with that select. If you are in Windows, you will have to go to Control Panel, System, Advanced, Environment Variables, and set NLS_LANG under System variables.
Oracle does at least a 'one-pass' conversion between client and database, but the problem is that there are so many layers between client and database, including your client software, that it is usually better to match your client NLS_LANG with the database setting.
It also depends how that character was inserted. It might have been inserted using a different client tool using a different NLS_LANG, so you might have to update your extended ASCII characters (or foreign characters) before you get a consistent view from your select.
Need to configure your systems NLS_LANG parameter, according to your language preferences. Here's a link:
http://www.nazmulhuda.info/setting-nls_lang-environment-variable-for-windows-and-unix-for-oracle-database
For example, we have letters like "ąčęėįšųū". So in order to see them in pl/sql, we set NLS_LANG with value "LITHUANIAN_LITHUANIA.BLT8MSWIN1257".
Hope it helps. Good luck.

How to change the V$NLS_PARAMETERS permanently?

I need to change V$NLS_PARAMETER . currently default NLS_LANGUAGE is American, I want to change it ENGLISH. Alter session modifies only the current session.
How to modify it permanently.
You can set NLS parameters at different levels
As initialization parameters on the instance/server.
SQL>alter system set V$NLS_PARAMETER = 'XXX' scope = both;
As environment variables on the client.
% setenv NLS_SORT FRENCH
As ALTER SESSION parameters.
SQL> ALTER SESSION SET V$NLS_PARAMETER = = 'XXX'
Any setting overrides the setting on a higher level. So setting it server side does not guarantee that the setting is used by all clients connecting.
If you want to make sure it is set for every client connecting use a logon trigger. Even then a user can explicitly override the 'default' setting

In oracle, how do I change my session to display UTF8?

I can't figure out Oracle's encryptic syntax for the life of me. This is Oracle 10g
My session's NLS_LANGUAGE is currently defaulting to AMERICAN.
I need to be able to display UTF8 characters.
Below are some of my attempts, all incorrect:
ALTER SESSION SET NLS_LANGUAGE='UTF8'
ALTER SESSION SET NLS_LANGUAGE='AMERICAN_AMERICA.UTF8'
What's the secret command?
The character set is part of the locale, which is determined by the value of NLS_LANG. As the documentation makes clear this is an operating system variable:
NLS_LANG is set as an environment
variable on UNIX platforms. NLS_LANG
is set in the registry on Windows
platforms.
Now we can use ALTER SESSION to change the values for a couple of locale elements, NLS_LANGUAGE and NLS_TERRITORY. But not, alas, the character set. The reason for this discrepancy is - I think - that the language and territory simply effect how Oracle interprets the stored data, e.g. whether to display a comma or a period when displaying a large number. Wheareas the character set is concerned with how the client application renders the displayed data. This information is picked up by the client application at startup time, and cannot be changed from within.
Okay, per http://www.oracle.com/technology/tech/globalization/htdocs/nls_lang%20faq.htm:
NLS_LANG cannot be changed by ALTER
SESSION, NLS_LANGUAGE and
NLS_TERRITORY can. However
NLS_LANGUAGE and /or NLS_TERRITORY
cannot be set as "standalone"
parameters in the environment or
registry on the client.
Evidently the "right" solution is, before logging into Oracle at all, setting the following environment variable:
export NLS_LANG=AMERICAN_AMERICA.UTF8
Oracle gets a big fat F for usability.
Therefore, before starting '$ sqlplus' on OS, run the followings:
On Windows
set NLS_LANG=AMERICAN_AMERICA.UTF8
On Unix (Solaris and Linux, centos etc)
export NLS_LANG=AMERICAN_AMERICA.UTF8
It would also be advisable to set env variable in your '.bash_profile' [on start up script]
This is the place where other ORACLE env variables (ORACLE_SID, ORACLE_HOME) are usually set.
just fyi - SQL Developer is good at displaying/handling non-English UTF8 characters.

ORACLE 11g case insensitive by default

I found in this article, that since ORACLE 10g, there is a way to make a particular connection-session compare strings case-insensitive, without needing any crazy SQL functions, using an ALTER SESSION.
Does anyone know if, in 11g, there might be a way to make the database to always operate in this mode by default for all new connection-sessions, thereby eliminating the need for running ALTER SESSIONs every time you connect?
Or perhaps, an additional parameter you could specify on your connection string that would turn the same on?
You could just set the NLS_SORT, NLS_COMP parameters mentioned in the article as the values in the the Oracle init file using the alter system set <parameter> = <value>; clause.
Info on using the alter system commands can be found here.
Here is a good link on the correct usage of the NLS_* parameters. Note that some settings of of the NLS_SORT parameter can/could cause performance issues, namely when it is not set to BINARY. The Oracle docs state:
Setting NLS_SORT to anything other
than BINARY causes a sort to use a
full table scan, regardless of the
path chosen by the optimizer. BINARY
is the exception because indexes are
built according to a binary order of
keys. Thus the optimizer can use an
index to satisfy the ORDER BY clause
when NLS_SORT is set to BINARY. If
NLS_SORT is set to any linguistic
sort, the optimizer must include a
full table scan and a full sort in the
execution plan.
Sure you can!
Get your friendly DBA to set these parameters:
ALTER SYSTEM SET NLS_COMP=LINGUISTIC SCOPE=SPFILE;
ALTER SYSTEM SET NLS_SORT=BINARY_AI SCOPE=SPFILE;
This is taken from my short article on How to make Oracle Case Insensitive
I tried using a logon trigger to issue these commands to get case-insensitive queries:
execute immediate 'alter session set NLS_SORT=BINARY_CI';
execute immediate 'alter session set NLS_COMP=LINGUISTIC';
And while that did give me CI, it also gave me unbelievably bad performance issues. We have one table in particular that, without those settings, inserts take 2 milliseconds. With those settings in place, inserts took 3 seconds. I have confirmed this by creating and dropping the trigger multiple times.
I don't know if doing it at the system level, as opposed to the session level with a trigger, makes a difference or not.
I found the same performance issue with inserts and nls in 11g r2! Luckily for me the performance hit was not significant enough requiring an app change.
If you can do without binary_ci for the INSERT, then I would do an alter session just before the insert and afterwards, so you don't have to drop the trigger

Resources