ajuda com função oracle

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
dark neo
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qui, 27 Set 2012 3:06 pm

Pessoal fiz esta função, mais não estou conseguindo termina-la

preciso somar as horas trabalhadas no final e retorna-las
segue abaixo a funcção

Selecionar tudo


create or replace function SOMA_DATA(dt_ini Date, dt_fim Date)
return varchar2 
as
data1 date;
data2 date; 
vdia varchar2(10);
vferiado INTEGER;
vtotal INTEGER;
begin

 data1 :=  dt_ini;
 data2 :=  dt_fim;

-- Enquanto data1 for menos que data2
WHILE data1 <= data2 LOOP
    
 SELECT TO_CHAR (TO_DATE (data1, 'MM/DD/YYYY'), 'DY')
    INTO vdia 
    FROM DUAL;  
 
-- verificando se na data passada existe é sabado ou domingo

 IF vdia IN ('SÁB','DOM')
  THEN
    EXIT;
 END IF;
 -- verificando se a data passada é feriado
  DBMS_OUTPUT.put_line(data1);
  SELECT COUNT(*) INTO vferiado FROM feriado WHERE dataferiado >= to_date(data1, 'dd/mm/rrrr')
  AND dataferiado <= to_date(data2, 'dd/mm/rrrr');

  IF vferiado > 0 THEN // ele não entra neste IF não sei porque
  DBMS_OUTPUT.put_line('entrou no if');
  return vferiado;
  
  else

-- arqui eu estou tenatando somar as horas e no final me dar o total de horas trabalhada no perido passado
    SELECT TO_CHAR(SYSDATE,'DD/MM/YYYY HH24:MI:SS') AS AGORA,
    TO_CHAR(SYSDATE + 10/1440, 'DD/MM/YYYY HH24:MI:SS')
    into vtotal
    FROM DUAL;
  
  end if;

return vtotal;
END LOOP;
return 

end SOMA_DATA;

pesssoal se puderem me ajudar a terminar isso, so iniciante em PL SQL , preciso de ajuda.

obrigado a todos abraço!!!
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE
att,

Daniel N.N.

Olha os exmplos de:
http://glufke.net/oracle/viewtopic.php? ... A7a#p32892
http://glufke.net/oracle/viewtopic.php? ... A7a#p33353

Mas qual é o problema que está dando?
está dando erro ou o calculo está errado???
Seja um pouco mais específico, que ajuda mais.
dark neo
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qui, 27 Set 2012 3:06 pm

Obrigado pela atenção noctifero

o que acontence é que preciso montar uma função que pegue um perido dataIni e datafim verificar se dataini é menor data fim no while enquanto isso for false pego a primeira data e verifico se ela é sab ou dom e consulto uma tabela de feriado verificando se a data consta na tab, feito isso preciso pegar as horas trabalhada no caso 12 horas e amazenar em uma variavel faço a proxima iteração faço o mesmo e amarzeno na variavel a função deve retornar o total de horas trabalhada neste periodo..

assim que eu estou fazendo ate agora:

Selecionar tudo


create or replace function SOMA_DATA(dt_ini in varchar2, dt_fim in varchar2)
return varchar2 
as
data1 date;
data2 date; 
vdia varchar2(10);
vferiado INTEGER;
vtotal INTEGER;
vlinha INTEGER;
vhora number;

horas_dia_trabalhada integer := 24;
minutos_hora integer := 60;
segundos_minuto integer := 60; 

total_horas_dia integer;
total_minutos_dia integer;
total_segundos_dia integer;


begin
vlinha := vlinha + 1;
 data1 :=  dt_ini;
 data2 :=  dt_fim;
 
total_horas_dia := horas_dia_trabalhada;
total_minutos_dia := minutos_hora * horas_dia_trabalhada;
total_segundos_dia := segundos_minuto * minutos_hora * horas_dia_trabalhada;
 
-- Enquanto data1 for menor que data

SELECT TO_CHAR(TO_DATE (data1), 'DY')
    INTO vdia 
    FROM DUAL;  
 
SELECT COUNT(*) INTO vferiado FROM feriado WHERE dataferiado >= to_date('10/10/2012')
  AND dataferiado <= to_date('10/10/2012');
-- verificando se na data passada é sabado ou domingo

 IF vdia IN ('SÁB','DOM')
  THEN
  return vdia;
 END IF;
 
 dbms_output.put_line(vferiado);

 IF vferiado = 1 THEN
 return 'è feriado';
 end if;
 
 vhora := datediff('HH',data1,data2);
 dbms_output.put_line(vhora * (-1));
 
 -- Pegando a data e somando 12 horas a ela.
dbms_output.put_line('+ 15 horas…: ' || to_char(data1 + (15 / total_horas_dia), 'dd/mon/yyyy HH24:mi:ss'));
dbms_output.put_line(data1);


return vtotal;

end SOMA_DATA;

esta dificil porque sou programador JAVA e tb nunca programei em plsql, se você puder me ajudar te agradeço.

abraço e obrgado pela atenção mas uma vez!!
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 318
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Cara eu já tinha visto o seu tópico mas estava tentando entender o que você precisava também.

Como você tem mais familiaridade com java você uma opção é criar uma função e executá-la dentro do banco.

Mas falando do seu problema, pelo o que eu entendi, dentro de um período você quer identificar os dias que são finais de semana e os feriados? Ou você quer descartá-los para pegar apenas os dias úteis?

Eu já via algumas soluções interessantes em outros tópicos aqui no próprio forum mesmo:
* Pessoal, como eu faço para pegar os dias úteis? alguém tem um select ou uma função que faça isso?

Selecionar tudo


with day_tab as (
select mon_dt + level - 1 dt,
       to_char(mon_dt + level - 1, 'DY', 'NLS_DATE_LANGUAGE=''ENGLISH''') dy
  from (select trunc(to_date(m || '/' || a, 'MM/YYYY'), 'MM') mon_dt
          from (select '02' m, '2010' a from dual))
connect by mon_dt + level - 1 <= last_day(mon_dt))
-- fim dos dados de exemplo
select dt,
       dy
  from day_tab
where dy in ('MON', 'TUE', 'WED', 'THU', 'FRI');
http://glufke.net/oracle/viewtopic.php?f=2&t=6519&p=25864&hilit=feriados#p25864
* Preciso efetuar um cálculo entre duas data considerando apenas os dias de semana

Selecionar tudo


select count(1) from
(
  select dia, to_char(dia, 'D') dia_semana
  from
  (
    select &dat_ini + level - 1 dia
    from   dual
    connect by level < &dat_fim - &dat_ini + 1
  ) d
)
where  dia_semana not in ( '1', '7' )
http://glufke.net/oracle/viewtopic.php?f=2&t=6400&p=25423&hilit=feriados#p25423
Veja se estas opções lhe ajudam ou pelo menos já da um clareada. Qualquer coisa posta ai.

Abç.,
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 318
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Segue uma outra função:

Selecionar tudo


create or replace FUNCTION DIAS_UTEIS( vDATA1 IN DATE, vDATA2 IN DATE) RETURN NUMBER IS 
  vtemp  number; 
  fer_01 varchar2(5) := '01/01'; 
  fer_02 varchar2(5) := '14/04'; 
  fer_03 varchar2(5) := '21/04'; 
  fer_04 varchar2(5) := '01/05'; 
  fer_05 varchar2(5) := '15/06'; 
  fer_06 varchar2(5) := '07/09'; 
  fer_07 varchar2(5) := '12/10'; 
  fer_08 varchar2(5) := '02/11'; 
  fer_09 varchar2(5) := '15/11'; 
  fer_10 varchar2(5) := '25/12'; 
begin 
  select count(dat)into vtemp 
  from (select vdata1 + rownum-1 dat from i_os where rownum <= (vdata2-vdata1)+1 ) 
  where to_char(dat, 'd') not in (1,7) 
        and (to_char(dat,'dd/mm') <> fer_01) 
        and (to_char(dat,'dd/mm') <> fer_02) 
        and (to_char(dat,'dd/mm') <> fer_03) 
        and (to_char(dat,'dd/mm') <> fer_04) 
        and (to_char(dat,'dd/mm') <> fer_05) 
        and (to_char(dat,'dd/mm') <> fer_06) 
        and (to_char(dat,'dd/mm') <> fer_07) 
        and (to_char(dat,'dd/mm') <> fer_08) 
        and (to_char(dat,'dd/mm') <> fer_09) 
        and (to_char(dat,'dd/mm') <> fer_10); 
  vtemp := vtemp - 1; 
  RETURN vtemp; 
end;  

Obs.: Dentre os meus arquivos acabei encontrando uma função mas não tenho referência do autor para poder creditá-lo;

Veja se ajuda.

Att.,
Responder
  • Informação