Olá,
Sabemos que na linguagem SQL não existe o tipo de dado Boolean. Bom, pelo menos no que se refere ao Oracle, o tipo de dado Boolean existe apenas dentro do PL/SQL. O motivo para eu estar escrevendo este artigo vem de um cenário na qual um desenvolvedor pediu um suporte para a equipe de analistas de banco de dados na qual atuo de forma a ajudá-lo a desvendar o erro "ORA-06553: PLS-382: a expressão é do tipo incorreto" que insistia em acontecer a todo momento em que ele chamava uma função no banco de dados através de uma consulta SQL. É aí que o tipo de dado Boolean entra na estória. Para simular a situação ocorrida, tenha como exemplo a função FC_IS_WEEKEND criada abaixo:
Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> create or replace function fc_is_weekend (p_date date)
2 return boolean
3 as
4 aux varchar2(3);
5 begin
6 select to_char (p_date,'DY','nls_date_language=AMERICAN') into aux from dual;
7 if aux in ('SAT','SUN')
8 then
9 return TRUE;
10 else
11 return FALSE;
12 end if;
13 end;
14 /
Função criada.
Vejamos o que acontece quando chamamos a função através de uma consulta SQL conforme demonstrado abaixo:
SQL> select fc_is_weekend(sysdate) from dual;
select fc_is_weekend(sysdate) from dual
*
ERRO na linha 1:
ORA-06552: PL/SQL: Statement ignored
ORA-06553: PLS-382: a expressão é do tipo incorreto
Perceberam o problema? A função foi criada tendo como propósito retornar um valor Booleano (TRUE/FALSE), ou seja, se uma data passada como parâmetro cair em um final de semana, então a função deverá retornar TRUE, senão a mesma deverá retornar FALSE. O erro "ORA-06553: PLS-382" ocorre exatamente pelo fato do SQL não entender o tipo de dado Booleano que está sendo retornado pela função. Neste caso, a função somente poderá ser usada apenas dentro de um bloco PL/SQL como demonstrado abaixo:
SQL> set serveroutput on
SQL> declare
2 aux boolean;
3 begin
4 aux := fc_is_weekend (sysdate);
5 dbms_output.put_line(sys.diutil.bool_to_int(aux));
6 end;
7 /
0
Procedimento PL/SQL concluído com sucesso.
Acima, eu chamei a função FC_IS_WEEKEND de dentro de um bloco PL/SQL e, para fins de demonstração, transformei o resultado para o tipo de dado numérico usando a função SYS.DIUTIL.BOOL_TO_INT de forma que o resultado pudesse ter sido mostrado. Neste caso, 0 (zero) significa FALSE. Enfim, uma forma de resolver este problema seria alterar a função existente, ou criar uma nova função conforme demonstrado a seguir:
SQL> create or replace function fc_is_weekend2 (p_date date)
2 return number
3 as
4 aux boolean;
5 begin
6 aux := fc_is_weekend(p_date);
7 if aux = TRUE
8 then
9 return 1;
10 else
11 return 0;
12 end if;
13 end;
14 /
Função criada.
SQL> select fc_is_weekend2(sysdate) from dual;
FC_IS_WEEKEND2(SYSDATE)
-----------------------
0
No mais, o ideal seria que o Oracle além de entender um overload da função dentro de uma package, na qual os parâmetros de entrada das funções seriam do mesmo tipo, mas o tipo de dados de saída seriam diferentes, fosse também capaz de perceber a origem da chamada de uma função (SQL ou PL/SQL) de forma a fazer a chamada para a função correta como demonstrado abaixo. A questão é que eu não saberia dizer realmente se existiria alguma vantagem nisso.
SQL> create or replace package pkg_teste
2 as
3 function fc_is_weekend (p_date date) return boolean;
4 function fc_is_weekend (p_date date) return number;
5 end;
6 /
Pacote criado.
SQL> create or replace package body pkg_teste
2 as
3 function fc_is_weekend (p_date date) return boolean as
4 aux varchar2(3);
5 begin
6 select to_char (p_date,'DY','nls_date_language=AMERICAN') into aux from dual;
7 if aux in ('SAT','SUN')
8 then
9 return TRUE;
10 else
11 return FALSE;
12 end if;
13 end;
14
15 function fc_is_weekend (p_date date) return number as
16 aux varchar2(3);
17 begin
18 select to_char (p_date,'DY','nls_date_language=AMERICAN') into aux from dual;
19 if aux in ('SAT','SUN')
20 then
21 return 1;
22 else
23 return 0;
24 end if;
25 end;
26 end;
27 /
Corpo de Pacote criado.
SQL> select pkg_teste.fc_is_weekend(sysdate) from dual;
select pkg_teste.fc_is_weekend(sysdate) from dual
*
ERRO na linha 1:
ORA-06553: PLS-307: muitas declarações de 'FC_IS_WEEKEND' são compatíveis com esta chamada
2 comentários:
Excelentes posts!!
parabéns pelo Blog
Olá Ronei,
Obrigado pela visita!
Abraços e até mais...
Legatti
Postar um comentário