No artigo de hoje vou comentar sobre como evitar a visualização ou formatação incorreta de caracteres, datas e números (também conhecida como desconfiguração de caracteres, como vejo muitos desenvolvedores comentar), que afeta muitas aplicações e que já vi muita gente buscar ajuda em fóruns. Esse problema é muito comum em aplicações desenvolvidas em qualquer linguagem de programação e SGBD, e para evitá-lo, no caso de SGBDs Oracle, é necessário entender os recursos de suporte à globalização, mais especificamente, o National Language Support ou NLS.
NLS pode ser usado para definir, através de parâmetros, configurações de terrritório, idioma e conjuntos de caracteres (character set) no BD ou sessão de um usuário. Essas configurações incluem a formatação de datas, números, moeda, linguagem, separador de caracteres em listas, sistema de calendário etc.
Os parâmetros de NLS podem ser especificados na criação do BD, ou depois, em 4 caminhos (no cliente ou servidor) e a maior parte deles possui um valor padrão. Os itens abaixo apresentam exemplos de caminhos em que eles podem ser configurados, seguindo uma ordem de precedência, em que os itens de menor número são de mais baixa precedência, ou seja, se você configurar um parâmetro através de uma variável de ambiente (ver item 2), ele poderá ser sobrescrito por um parâmetro de sessão (ver item 3), que por sua vez, também poderá ser sobrescrito por um parâmetro de uma função SQL (ver item 4):
Os parâmetros de NLS podem ser especificados na criação do BD, ou depois, em 4 caminhos (no cliente ou servidor) e a maior parte deles possui um valor padrão. Os itens abaixo apresentam exemplos de caminhos em que eles podem ser configurados, seguindo uma ordem de precedência, em que os itens de menor número são de mais baixa precedência, ou seja, se você configurar um parâmetro através de uma variável de ambiente (ver item 2), ele poderá ser sobrescrito por um parâmetro de sessão (ver item 3), que por sua vez, também poderá ser sobrescrito por um parâmetro de uma função SQL (ver item 4):
1- Configurando parâmetros NLS através de parâmetros de inicialização (instância) no Banco de Dados:
2- Configurando parâmetros NLS através de variáveis de ambiente no Sistema Operacional: NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
3- Configurando parâmetros NLS através de parâmetros de sessão:
alter session set NLS_DATE_FORMAT = 'dd/mm/yyyy'
4- Configurando parâmetros NLS através de parâmetros de funções SQL:
TO_CHAR(hiredate, 'DD/MON/YYYY', 'nls_date_language = FRENCH')Segue abaixo uma lista com os principais parâmetros de NLS, contendo nome e descrição do parâmetro, o valor padrão e o escopo em que ele pode ser configurado. Observe pela coluna valor padrão, que muitos parâmetros herdam valores de outros parâmetros. Por exemplo, NLS_DATE_FORMAT herda um valor do parâmetro NLS_TERRITORY:
Parâmetro
|
Descrição
|
Valor padrão
| Escopo: I=Instância, E= Variável ambiente, A= Sessão |
NLS_CALENDAR
|
Sistema de calendário
|
Gregorian
|
I, E, A
|
NLS_COMP
|
Operador de comparação SQL, PL/SQL
|
Binary
|
I, E, A
|
NLS_CREDIT
|
Símbolo de contabilidade de crédito
|
NLS_TERRITORY
|
-, E, -
|
NLS_CURRENCY
|
Símbolo da moeda local
|
NLS_TERRITORY
|
I, E, A
|
NLS_DATE_FORMAT
|
Formato de data
|
NLS_TERRITORY
|
I, E, A
|
NLS_DATE_LANGUAGE
|
Linguagem para nomes de dias e meses
|
NLS_LANGUAGE
|
I, E, A
|
NLS_DEBIT
|
Símbolo de contabilidade de dédito
|
NLS_TERRITORY
|
-, E, -
|
NLS_ISO_CURRENCY
|
Símbolo internacional ISO da moeda
|
NLS_TERRITORY
|
I, E, A
|
NLS_LANG
|
Linguagem, território e conjunto de caracteres (character set)
|
AMERICAN_AMERICA.
US7ASCII |
-, E, -
|
NLS_LANGUAGE
|
Linguagem
|
NLS_LANG
|
I, -, A
|
NLS_LENGTH_SEMANTICS
|
Valor indicando como as strings são tratadas
|
Byte
|
I, -, A
|
NLS_LIST_SEPARATOR
|
Caractere separador de itens em uma lista
|
NLS_TERRITORY
|
-, E, -
|
NLS_MONETARY_CHARACTERS
|
Símbolo monetário para dólar e centavos (ou seus equivalentes)
|
NLS_TERRITORY
|
-, E, -
|
NLS_NCHAR_CONV_EXCP
|
Relata perda de dados durante uma conversão de tipos de caracteres
|
-, E, -
| |
NLS_NUMERIC_CHARACTERS
|
Separador decimal e de gupo (milhar, milhão etc.)
|
NLS_TERRITORY
|
I, E, A
|
NLS_SORT
|
Sequência de ordenação de caracteres
|
NLS_LANGUAGE
|
I, E, A
|
NLS_TERRITORY
|
Território
|
NLS_LANG
|
I, -, A
|
NLS_TIMESTAMP_FORMAT
|
Timestamp
|
NLS_TERRITORY
|
I, E, A
|
NLS_TIMESTAMP_TZ_FORMAT
|
Timestamp com Timezone
|
NLS_TERRITORY
|
I, E, A
|
NLS_DUAL_CURRENCY
|
Símbolo de moeda Dual
|
NLS_TERRITORY
|
I, E, A
|
Configurando o parâmetro NLS_LANG
Um dos principais parâmetros para configurar NLS é o parâmetro NLS_LANG. Se ele for corretamente configurado, dificilmente você precisará configurar mais algum outro parâmetro. NLS_LANG permite configurar através de uma variável de ambiente (no cliente), a linguagem, território e conjunto de caracteres que serão usados pela aplicação.
A linguagem especifica o idioma das mensagens Oracle, ordenação, nomes de dias e meses. Cada linguagem tem um nome único, como por exemplo: AMERICAN (valor padrão), FRENCH e GERMAN.
O território especifica a formatação de data, moeda e números. Cada território tem um nome único, como por exemplo: AMERICA, FRANCE e CANADA. Se um território não for especificado, ele herda um valor da linguagem.
O conjunto de caracteres (character set), especifica, como o próprio nome diz, o conjunto de caracteres que será usado pela aplicação cliente. Exemplos: US7ASCII, WEISO8859P1, JA16EUC. Cada linguagem tem um conjunto de caracteres associado que é configurado se um valor não for especificado em NLS_LANG.
Os 3 valores de NLS_LANG podem ser configurados através de muitas combinações, como por exemplo:
NLS_LANG=AMERICAN_AMERICA.US7ASCII
NLS_LANG=FRENCH_CANADA.WE8DEC
Obs.: Combinações ilógicas podem ser configuradas, mas não funcionarão apropriadamente. Se por exemplo, for configurada uma especificação de linguagem Japanese usando um conjunto de caracteres Western European, tal como WE8DEC, você estará inapto a armazenar dados na linguagem Japanese, pois WE8DEC não suporta dados japoneses:
NLS_LANG=JAPANESE_JAPAN.WE8DEC
Testando NLS_LANG
A configuração de NLS_LANG deve ser realizada através de uma variável de ambiente no cliente, portanto, irei demonstrar no passo-a-passo abaixo, a configuração e uso desse parâmetro em um cliente Windows que se conecta em um BD Oracle remoto. Para efetuar os testes é necessário ter o schema HR instalado (para mais informações sobre o HR, leia o artigo Instalando o schema de exemplo HR):
Passo 1- No cliente Windows abra um janela de prompt de comandos (ver Figura 1):
Figura 1 - Janela de prompt de comandos no Windows |
Passo 2- Configure uma variável de ambiente com o nome NLS_LANG e valor American_America.WE8ISO8859P1 (ver Figura 2):
Figura 2 - Configurando NLS_LANG=American_America.WE8ISO8859P1 |
Passo 3- Conecte-se no BD remoto, através do SQL Plus, fornecendo um nome/senha de usuário válidos, que tenha acesso às tabelas do schema HR (ver Figura 3):
Figura 3 - Conectando-se no BD remoto através do SQL Plus |
Passo 4- Execute a instrução SQL abaixo e veja que as datas e números estão formatados de acordo com o padrão americano ('dd-MON-yy'), configurado previamente através da variável NLS_LANG (ver Figura 4):
SELECT first_name,
hire_date,
salary,
ROUND(salary/12,2)
FROM hr.employees
where rownum < 5;
Figura 4 - Executando SQL com NLS no padrão americano |
Passo 5- Saia do SQL Plus e configure novamente a variável de ambiente NLS_LANG, mas desta vez, com o valor French_France.WE8ISO8859P1 (ver Figura 5) e repita novamente o Passo 3 (conexão ao BD com o SQL Plus):
Figura 5 - Configurando NLS_LANG=French_France.WE8ISO8859P1 |
Passo 6- Execute novamente a instrução SQL do Passo 4 e veja que agora as datas e números estão formatados de acordo com o padrão francês ('dd/mm/yy'), e não mais no padrão americano (ver Figura 6):
Figura 6 - Executando SQL com NLS no padrão francês |
Passo 7- Para demonstrar algo mais, iremos configurar agora, no nível da sessão (via SQL Plus), o parâmetro NLS_DATE_FORMAT, sobrescrevendo o valor herdado do território (ver NLS_LANG configurado préviamente), para que o ano das datas seja visualizado no formato com 4 dígitos e executaremos novamente a instrução SQL do Passo 4 para ver o novo resultado (ver Figura 7):
Figura 7 - Configurando NLS_DATE_FORMAT para exibir ano com 4 dígitos |
Bom pessoal, para finalizar o artigo, quando for necessário identificar quais são os parâmetros de NLS do BD, faça um SELECT na visão NLS_DATABASE_PARAMETERS. Se você precisa identificar os parâmetros de NLS da instância, consulte NLS_INSTANCE_PARAMETERS. Se você precisa identificar os parâmetros NLS da sessão de usuário atual, consulte a visão NLS_SESSION_PARAMETERS, como no exemplo abaixo:
select * from nls_session_parameters;
Obs.: Lembre-se que parâmetros de NLS no nível da sessão sobrescrevem os parâmetros no nível da instância, que por sua vez, sobrescrevem os parâmetros no nível do BD, portanto, se quiser saber, por exemplo, o formato de data que a sua aplicação está usando, consulte NLS_SESSION_PARAMETERS.
Por hoje é só!
[]s
Referências:
- Oracle Documentation: http://oracleonline.info/setting_nls.html
E ae Fábio,
ResponderExcluirMuito bom esse artigo, o assunto é muito pertinente , semanas atrás tivemos um problema de NLS, pois no client que executava a query havia uma configuração específica de NLS, então colocamos um comando para alterar o NLS da session e executar a query, independente do client.
Show de bola.
Grande Abs.
Pra variar...mais um bom artigo.
ResponderExcluirabs,
Marcio
Muito bom o Artigo Fábio, já me ajudou em um problema que eu tinha.
ResponderExcluirQuanto ao exportar para excel creio que era no NLS_LIST_SEPARATOR .
Porém ainda quando eu exporto para o excel estou com problema quanto a textos com acentos.
"Crédito" ainda acaba aparecendo como CRÉDITO
No select mostra normalmente, o problema é ao exportar.
Alterei os parâmetros na alter session.
O que pode estar ocorrendo ainda?
O seu problema agora é a codificação de caracteres do arquivo no EXCEL.
ExcluirEla tem que ser compatível com o character set do BD. Em arquivos texto por exemplo vc pode salvar o arquivo usando N codificações (UTF* ou ANSI*). Vc tem que descobrir qual delas é compatível e gerar o arquivo na codificação certa!
[]s
Bom dia estou aprendendo banco de dados oracle e me deparei com um erro
ResponderExcluirquando tento inserir dados em campos float...estou usando o APEX do oracle e quando tento de forma visual editar os dados, os campos float estao bloqueados.... poderia ajudar
Marcos
Olá Marcos, este artigo não tem nada a ver com Apex, sugiro que você procure ajuda em algum fórum ou artigo de quem escreveu sobre "Apex". De qq modo conheço Apex, mas não sei o porquê do erro. Eu lhe responderia se soubesse a resposta.
Excluir[]s
Bom dia!
ResponderExcluirÉ possível corrigir o legado? todos os dados que já estão na base? Obrigado
Sim, mas é bem trabalhoso e também arriscado perder dados. Pesquise sobre CSSCAN e CSALTER: https://oracle-base.com/articles/10g/character-set-migration.
ExcluirParabens resolveu em uma aplicação delphi (NLS_LANG)
ResponderExcluirObrigado pelo feedback!
ExcluirEu estou com problema no Access com banco de dados oracle.
ResponderExcluirTodos os valores de milhar retornamultiplicado por 100. Ja mudei o NLS_LANG de
BRAZILIAN PORTUGUESE_BRAZIL.WE8MSWIN1252
para
AMERICAN_AMERICA.WE8ISO8859P1
Mesmo assim continuo com o problema dos milhares.