domingo, 22 de novembro de 2009

BD-Oracle [Acentos no 10g XE (Configuração de NLS)]

Configuração de NLS

As configurações de NLS (National Language Support Guide) são responsáveis pelas configurações regionais do banco de dados conforme a necessidade.
As configurações da NLS podem ter seus valores diferenciados nas configurações de um DataBase, de uma Seção ou de uma Instancia
Se o banco está instalado com um characterset (conjunto de caracteres) onde cada símbolo especial (como os acentos e cedilhas) ocupa dois bytes (como os characterset padrões UTF-8, e mais alguns), ao se tentar gravar em um campo tipo Char(3) a string 'CCÇ' , ocupará um byte pra cada "C" e dois bytes para o "Ç" e o banco exibira uma mensagem de erro informando que esta sendo tendado gravar um dado muito grande para o tamanho do campo.
Conforme pesquisado esse erro não tem a ver com a variável de ambiente de NLS, mas sim com o characterset configurado.
O characterset AL32UTF8 é multibyte, ou seja, dependendo do idioma, cada caracter pode utilizar 2 ou 3 bytes.
Se não se quiser alterar o characterset do banco ou se não conseguir alterar o banco, ao invés de Char(3) ou VarChar(3) pode ser usado os tipos Nchar(3) ou NvarChar(3), esses datatypes (tipos de dados) alocam espaço não em bytes, mas em caracteres, num Nchar(3) ou NvarChar(3) sempre pode se gravar 3 caracteres, não importando o characterset atual.

Visualizar as configurações atuais da NLS

Podem ser utilizados os seguintes comandos para se visualizar os valores dos parâmetros da NLS:

=> Select * from nls_database_parameters
=> Select * from nls_session_parameters
=> Select * from nls_instance_parameters

Exibe os valores de database_parameters
=> SELECT name,value$ from sys.props$ where name like '%NLS_LANG%'
=> SELECT name,value$ from sys.props$ where name like '%NLS_CHAR%'
=> SELECT name,value$ from sys.props$ where name like '%_CHARACTER%'
=> Select nls_charset_id('WE8MSWIN1252') from dual
=> Select nls_charset_name(178) from dual

Variável de ambiente NLS_LANG

Há uma variável de ambiente chamada NLS_LANG praticamente todas as atividades que você faz através de uma sessão sql, são regidas pela variável de ambiente NLS_LANG que pode ser configurada para:
=> Set NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252
=> Set NLS_LANG=BRAZILIAN PORTUGUESE_BRAZIL.WE8MSWIN1252
=> Set NLS_LANG=Brazilian Portuguese_Brazil.WE8ISO8859P1

Chave de registro do Windows

A definição de NLS_LANG também é armazenada em uma sub chave de registro:
=> HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient10g_home1

Alterações dos valores de NLS

Para se alterar os valores das configurações da NLS temos os seguintes comandos:

=> Alter Session Set NLS_LANGUAGE = "PORTUGUESE"
=> Alter Session Set NLS_TERRITORY = "BRAZIL"
=> Alter System Set NLS_LANGUAGE='BRAZILIAN PORTUGUESE' scope=spfile;
=> Alter System Set NLS_TERRITORY='BRAZIL' SCOPE=SPFILE;
=> Update sys.props$ set value$ = 'WE8MSWIN1252' where name = 'NLS_NCHAR_CHARACTERSET';
=> Update sys.props$ set value$ = 'WE8MSWIN1252' where name = 'NLS_CHARACTERSET';

Para alterar o charset do banco oracle 10 XE, também pode se executar a seguinte seqüência de comandos no SqlPlus. Entre no SqlPlus com o usuário sys as sysdba, depois derruba o banco, altera o charset e inicia o banco novamente. Segue os comandos a baixo

#sqlplus /nolog

conn sys as sysdba;

SHUT;
STARTUP RESTRICT;
Alter database character set INTERNAL_USE WE8ISO8859P1;
SHUT;
STARTUP;

Atenção!!
Algumas alterações nos padrões da NLS no Oracle 10g XE podem causar um erro na pagina de acesso ao banco. Mas se você não utiliza a pagina não terá nenhum problema.

Os comandos listados abaixos foram testados mas não tiveram um retorno possitivo. Mantive os aqui para efeito de consulta.
update nls_database_parameters set NLS_CHARACTERSET = To_charset('WE8MSWIN1252')
update nls_database_parameters set NLS_CHARACTERSET = nls_charset_name(178)
Alter database SET NLS_CHARACTERSET = NLS_CHARSET_ID('WE8MSWIN1252')
Alter database SET NLS_CHARACTERSET = nls_charset_name(178)
Alter session SET NLS_CHARACTERSET = NLS_CHARSET_ID('WE8MSWIN1252')
Alter session SET NLS_CHARACTERSET = nls_charset_name(178)
Alter session SET NLS_CHARACTERSET = 178
ALTER DATABASE CHARACTER SET WE8MSWIN1252

Resultado de testes.

Instalado um banco Oracle 10g XE foi observado que ele vem por default com as configurações da NLS
da seguinte forma:
Em session:
NLS_LANGUAGE = 'BRAZILIAN PORTUGUESE'
NLS_TERRITORY='BRAZIL'
NLS_ISO_CURRENCY='BRAZIL'
NLS_DATE_LANGUAGE='BRAZILIAM PORTUGUESE'
Em database:
NLS_LANGUAGE='AMERICAN'
NLS_TERRITORY='AMERICA'
NLS_ISO_CURRENCY='AMARICA'
NLS_DATE_LANGUAGE='AMERICAN'
NLS_CHARACTERSET='AL32UTF8'
NLS_NCHAR_CHARACTERSET='AL16UTF16'

As configurações de CHARACTERSET só existem no grupo database.
Para que os caracteres acentuados não ocupem 2 ou mais bytes é necessário alterar o NLS_CARACTERSET para 'WE8MSWIN1252'

Nota: Um campo do tipo varchar com tamanho 35 se for gravado nele um ou mais caracteres acentuados não há problema desde que não seja ocupado todo o tamanho definido no campo. Ex: Campo nome com tamanho 25 se for gravado nele “José da Conceição” (18 caracteres) não haverá problema, mas se for gravado “José da Conceição de Oliveira Pinto” (35 caracteres sendo 3 com acentos) causara um erro na gravação onde o banco ira informar que esta tentando se gravar 38 caracteres num campo de 35.

Conclusões:
Ao se alterar o CHARACTERSET ou qualquer um dos parâmetros da NLS do grupo database a pagina de administração do banco via browser fica inacessível, assim como a navegação pelo SqlDeveloper também fica prejudicada pois ao se logar no banco é exibida uma mensagem informando que o caracterset atual não é reconhecido, e não é exibida a lista de objetos do banco (tabelas, views, ...), mas ao se digitar uma instrução SQL ele processa normalmente e acessando o banco por outro browser como o da EMSmanager ele funciona normalmente. Também funcionam normalmente os acessos via sistema ou via SQLPlus.

Um comentário:

Quem sou eu

Minha foto
Profissional da area de informática desde os XT. Casado 3 filhos. Programando atualmente em Delphi,Clipper com xHarbour e PHP as vezes. Já programei em VB, era o rei dos bats,rs algumas experiências com C++, C#.Net e Java. Fã de documentários de ciências e tecnologias