Вопрос

У меня есть праздничный стол, который содержит данные

    HOLIDAYDA DESCRIPTION
   --------- --------------------
   19-JAN-11 to
   17-JAN-11 to
   10-JAN-11 new day

Теперь я хочу первый рабочий день недели. Т.е. если я передаю «12-я январь-2011» в качестве ввода, я хочу, чтобы O / P как 11 - январь-2011 как 1-й рабочий день, потому что 10-Jan-2011 - это праздник.

Вот мой код:

create or replace procedure sample as
   l_dStartDay date;
   l_dHolidayDate date;
begin

    select trunc(to_date(sysdate),'Day') 
      into l_dStartday 
      from dual;

 dbms_output.put_line('first day of the week ');
 dbms_output.put_line(l_dStartDay);

 for i in 2..5 Loop
   select holidaydate 
     from holiday 
     into l_dHolidayDate 
    where holidaydate = (l_dStartDay + i);

  if(l_dHolidaydate is null) then
    dbms_output.put_line(l_dStartDay+i);
  end if;
exit;
end loop;
end;

Я составил вышеуказанную программу, но с "Процедура, созданная с ошибками компиляции."

Недавно добавленные: Опоследствие ошибок:

 LINE/COL ERROR
 -------- -----------------------------------------------------------------
 9/1      PL/SQL: SQL Statement ignored
 9/33     PL/SQL: ORA-00933: SQL command not properly ended

Ошибка:

BEGIN sample; END;
      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object SYSTEM.SAMPLE is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Может ли кто-нибудь сказать мне причину ошибки? Если возможно, скажите мне решение?

Это было полезно?

Решение

«Я составил вышеуказанную программу, но с Procedure created with compilation errors"

Если вы используете IDE, такие как Toad или SQL Developer, он автоматически отображает ошибки компиляции. В противном случае они доступны в SQL * Plus, используя эту команду:

SQL>    show errors

Также есть просмотры, такие как user_errors, которые мы можем запросить.

Проблема, скорее всего, оператор SELECT, поскольку в пункте «В» следует следовать сразу после проекции:

   select holidaydate 
     into l_dHolidayDate 
     from holiday 
    where holidaydate = l_dStartDay + i);

Разум вас, это также выглядит не так:

select trunc(to_date(sysdate),'Day') 

Sysdate уже дата, хотя более поздние версии Oracle, как правило, больше прощают использовать To_date на столбце Дата. При усечении элемента времени с даты нет необходимости включать в себя маску формата, поскольку это поведение по умолчанию:

trunc(some_date_variable)

Нам нужно только включить маску, если (сказать) мы хотим первый день месяца:

trunc(some_date_variable, 'MON')

Если вы хотите найти первый день недели, это сделает это:

SQL> select
  2      trunc(to_date('01-DEC-2010', 'DD-MON-YYYY'), 'D') start_of_wk
  3  from dual
  4  /

START_OF_
---------
29-NOV-10

SQL>

Обратите внимание, что первый день недели зависит от обстановки территории. На некоторых территориях первый день недели - рабочий день (например, в понедельник в Великобритании) в других не так (воскресенье - это день 1 в США). Так что может быть необходимо добавить смещение.


Как только вы решите ошибки компиляции, вы найдете ошибки времени выполнения SEM, вероятно, относящиеся к необразованным исключениям NO_DATA_FOUND. Это связано с тем, что ваш запрос поиска не будет возвращать NULL, когда он не найдет соответствующую запись, он не удастся.

Это простая процедура. Он использует решение SQL, потому что SQL является наиболее эффективным способом делать вещи. Внутренний запрос использует соединение путем трюка для генерации набора дат воздействия результатов. Затем это уменьшено оператором Minus Set, которое отфильтрует любые праздники в диапазоне этой недели. Наконец внешний запрос возвращает самую раннюю дату из запроса.

create or replace procedure get_first_working_day 
    ( p_tgt_date in date )
is
    l_st_day date := trunc(p_tgt_date, 'D');
    l_working_day date := trunc(p_tgt_date, 'D');
begin
    dbms_output.put_line('first day of week = '||l_st_day);

    select min(day_of_wk)
    into l_working_day
    from ( select l_st_day + (level-1) as day_of_wk
           from dual
           connect by level <= 5
           minus
           select holidaydate
           from hols
           where holidaydate between l_st_day and l_st_day + 4 );

    dbms_output.put_line('first working day of week = '||l_working_day
                        ||'::'|| to_char(l_working_day, 'DAY'));

end get_first_working_day;
/

Учитывая эти тестовые данные (которые отражают византийское состояние британских банковских праздников) ...

SQL> select holidate from hols
  2  order by 1
  3  /

HOLIDAYDA
---------
25-DEC-10
26-DEC-10
27-DEC-10
28-DEC-10
01-JAN-11
03-JAN-11

6 rows selected.

SQL>

... вот процедура в действии:

SQL> set serveroutput on size unlimited
SQL>
SQL> exec get_first_working_day (sysdate)
first day of week = 10-JAN-11
first working day of week = 10-JAN-11::MONDAY

PL/SQL procedure successfully completed.

SQL>
SQL> exec get_first_working_day (to_date( '04-JAN-2011', 'DD-MON-YYYY'))
first day of week = 03-JAN-11
first working day of week = 04-JAN-11::TUESDAY

PL/SQL procedure successfully completed.

SQL>
SQL> exec get_first_working_day (to_date( '01-JAN-2011', 'DD-MON-YYYY'))
first day of week = 27-DEC-10
first working day of week = 29-DEC-10::WEDNESDAY

PL/SQL procedure successfully completed.

SQL>

Кстати, это очень плохое практика:

PLS-00905: object SYSTEM.SAMPLE is invalid

Не используйте встроенные системы или системные аккаунты для вашей собственной работы. Слишком большой шанс что-то сломать. Создайте новую учетную запись пользователя.

Другие советы

Я предполагаю, что линия

where holidaydate = l_dStartDay + i);

не так, как у него есть ) где это не должно быть.

Помимо уже упомянутых ошибок, попробуйте удалить пункт «Выход», поскольку этот цикл произойдет за фиксированное количество раз. Кроме того, попробуйте уточнить имя блока при завершении блока, как в следующем:

    LOOP    
    ...
    END LOOP;
END ObjectName;

Где ObjectName - это ваша программа верхнего уровня. Здесь это будет «образец», так что:

    LOOP
    ...
    END LOOP;
END sample;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top