NLS_LENGTH_SEMANTICS - Why not in the init.ora?
By Mike Dietrich on May 11, 2012
.Few days ago at the Upgrade and Migration Workshop in Hamburg when I did talk about Unicode Migrations a customer had an interesting question.
"Why does the documentation states NOT to set NLS_LENGTH_SEMANTIC parameter to CHAR in the init.ora/spfile to enable char semantics for newly build objects by default?"
Honestly I was not aware of that hint. So I did some research and tried to get an answer from the developers.
The documentation says clearly not to set that parameter permanently:
- Oracle Database Reference on NLS_LENGTH_SEMANTICS
Oracle strongly recommends that you do NOT set the
CHARin the instance or server parameter file. This may cause many existing installation scripts to unexpectedly create columns with character length semantics, resulting in runtime errors, including buffer overflows.
- Oracle Database Globalization Support Guide on NLS_LENGTH_SEMANTICS
- Same warning as above - but also states:
NLS_LENGTH_SEMANTICSdoes not apply to tables created in the
SYSschema. The data dictionary always uses byte semantics. Tables owned by
SYSalways use byte semantics if the length qualifier
CHARis not specified in the table creation DDL.
And my colleague from Poland, Sergiusz Wolicki did reply (as always) very quickly (thanks!!!):
"The warning is general as the problem may affect Oracle data dictionary scripts for schemas such as SYSTEM, CTXSYS, ORDSYS, XDB, SYSMAN, Oracle application scripts for schemas such as APEX_030000, APPL, APPLSYS, GL, and other eBS or Peoplesoft or JDE, but also third party prepackaged applications and customer's own legacy stuff.
The recommendation is to avoid the dependency on the parameter altogether. The character and byte length semantics should be explicitly specified in column definitions and PL/SQL code:
CREATE TABLE emp( ..., first_name VARCHAR2(100 CHAR), last_name VARCHAR2(100 CHAR) )
CREATE PROCEDURE read_emp IS
v_full_name VARCHAR2(202 CHAR);
SELECT first_name, last_name INTO v_first_name, v_last_name FROM emp WHERE ...;
v_full_name := v_last_name || ', ' || v_first_name;
If you find specifying the data type and the length explicitly as an obvious thing, you should also expect that the length semantics (length units) are specified explicitly.
If you need to migrate existing scripts quickly, put an ALTER SESSION SET NLS_LENGTH_SEMANTICS=CHAR at the beginning of each script and after each CONNECT command in the script. "