GPO ( Grupo de Profissionais Oracle )
A maior comunidade Oracle do Brasil !

ANSI e economia de digitação, ou como ser preguiçoso de maneira positiva

Há muuuito tempo (ou pelo menos desde o Oracle versão 10gR2, ie, desde 2005 para quem não conta o tempo por releases do RDBMS Oracle) a Oracle introduziu vários ‘atalhos de sintaxe’ exigidos pelo comitê ANSI (que é quem padroniza a linguagem SQL e alguns recursos básicos para RDBMSs), que em alguns casos podem poupar uns tantos caracteres na sua digitação – muita gente (estranhamente) não sabia/não sabe disso até hoje e ainda fica surpresa quando demonstro essa novidade de “anteontem” (nem de ontem é , é mais velha que isso), o que me levou a escrever esse artigo….

Sem mais delongas, vamos a elas, ou pelo menos a algumas mais importantes (sim, eu TAMBÉM vou poupar uns toques no teclado e meu tempo não listando absolutamente TODAS, só algumas mais úteis 😉 , que seguem abaixo :

1. DATE LITERALS : como é de conhecimento geral, não há um formato de datas padrão e único num database Oracle – se você usar uma string simples num valor a ser manipulado numa coluna DATE, a string é convertida para DATE usando o formato que foi especificado pela sessão que conectou, ou o formato indicado nos parâmetros de inicialização… Por exemplo, se numa tabela T eu tenho uma coluna DT do tipo DATE, se eu escrever algo do tipo:

INSERT INTO T (DT) VALUES ('01/12/2020'); 

Se a sessão conectada estiver especificado dia/mes/ano com 4 dígitos como o formato de data default OK, isso funciona certinho … Porém, se for outro o formato em uso (essas coisas são ABSOLUTAMENTE alteráveis a qualquer tempo), a conversão implícita falhará miseravelmente…

A alternativa tradicional é fazer uma conversão indicando o formato, assim:

INSERT INTO T (DT) VALUES (TO_DATE('01/12/2020', 'dd/mm/yyyy') ); 

O que funciona, blz… Mas desde muito tempo atrás nós dispomos da sintaxe ANSI, que faz uma conversão usando o formato fixo de YYYY-MM-DD sempre, aí o mesmo INSERT seria escrito como:

INSERT INTO T (DT) VALUES (DATE '2020-12-01'); 

E pronto, esse código NUNCA vai falhar por causa de parâmetros/ajustes no database e economizei uns caracteres em relação à versão com TO_DATE…
 
DICA: no padrão ANSI esse formato DATE só contém ano, mês e dia : para representar HORÁRIO vc usa TIMESTAMP ao invés de DATE, e aí a máscara implícita é: ano-mês-dia hora-minuto-segundo.fração de segundo…

2. STRINGs CONTENDO ASPAS-SIMPLES : desde quase que a criação da linguagem SQL (e no Oracle, isso foi herdado pelo PL/SQL também), o caracter usado para delimitar uma string foi ‘ , ie, aspas-simples : isso causou e causa ainda algumas confusões quando se deseja criar uma string que contenha esse caracter também….

Por exemplo , quero montar a string :

MEU NOME É CHIAPPA

ok, faço isso diretamente abrindo e fechando a string com aspas simples:

scott@DESENV:SQL>select 'MEU NOME É CHIAPPA' as COLUNA_STRING from dual;

COLUNA_STRING 
------------------ 
MEU NOME É CHIAPPA 

scott@DESENV:SQL>

Agora suponha que eu quero montar a string:
 
OS SOBRENOMES O’MALLEY E O’HARA SÃO IRLANDESES
 
Tá vendo as aspas simples contidas na string ??? Isso vai causar confusão, já que o Oracle espera obter aspas apenas no início e no fim da string, não no meio:

scott@DESENV:SQL>select 'OS SOBRENOMES O'MALLEY E O'HARA SÃO IRLANDESES' as COLUNA_STRING from dual;

select 'OS SOBRENOMES O'MALLEY E O'HARA SÃO IRLANDESES' as COLUNA_STRING from dual
                               *
ERRO na linha 1:
ORA-00923: FROM keyword not found where expected

scott@DESENV:SQL> 

O erro é EXATAMENTE ISSO, ele encontrou um fecho de string ANTES do término efetivo da string, se confundiu todo, olha só a posição do * que indica o local do erro…. A alternativa tradicional no Oracle era você duplicar as aspas-simples internas da string, tipo:

scott@DESENV:SQL>select 'OS SOBRENOMES O''MALLEY E O''HARA SÃO IRLANDESES' as COLUNA_STRING from dual;

COLUNA_STRING
----------------------------------------------
OS SOBRENOMES O'MALLEY E O'HARA SÃO IRLANDESES

scott@DESENV:SQL>   

Mas isso é inconveniente e difícil de ler em alguns casos… Desde muitos anos atrás porém (supresa#2, novidade de museu #2) a Oracle adotou a alternativa ANSI, que é você Indicar um caracter alternativo de abertura e fechamento de string… No caso abaixo vou usar o caracter ! Mas posso usar qualquer caracter ASCII exibível em princípio:

scott@DESENV:SQL>select q'!OS SOBRENOMES O'MALLEY E O'HARA SÃO IRLANDESES!' as COLUNA_STRING from dual;

COLUNA_STRING
----------------------------------------------
OS SOBRENOMES O'MALLEY E O'HARA SÃO IRLANDESES 

No meu exemplo até que não poupei tantos caracteres assim evitando duplicar as aspas simples, mas há casos em que essa nova sintaxe ANSI vale a pena… E é claro, há algumas possibilidades mais que essa sintaxe oferece (como montar strings UNICODE, ou usar pares de caracteres pré-definidos comuns como abertura e fechamento tais como <>, () e {}, consulte a documentação Oracle da sua versão….
 
3. INTERVAL : tradicionalmente os SGBDs relacionais (e o Oracle em particular) só possuíam datatypes para registras datas e horas, não para armazenar um intervalo de tempo. Assim, o procedimento era manter uma coluna de início e uma coluna de final e calcular o intervalo via aritmética de datas….

Com a criação pelo comitê ANSI de um datatype próprio para isso (e a adoção dessa exigência pela Oracle), foi implementada uma nova sintaxe para indicar a conversão de uma string para esse datatype:

scott@DESENV:SQL>select INTERVAL '123-2' YEAR(3) TO MONTH as INTERV_123_ANOS_E_2_MESES from dual;

INTERV_123_ANOS_E_2_MESES
---------------------------------------------------------------------------
+123-02

scott@DESENV:SQL> 

Nem todas as linguagens de programação e/ou tools clientes/de usuário estão aptas a reconhecer e usar o novo datatype de interval mas vale a pena conhecer e usar se ele estiver disponível para você, e para esses casos a sintaxe ANSI de conversão demonstrada pode ser uma mão na roda, mais prática do que as funções built-in de conversão como TO_YMINTERVAL, TO_DSINTERVAl, etc….

Abraços

Share

You may also like...

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *