Oracle: la ricezione di ORA-06550 e PLS-00905
Domanda
Ho una tabella di vacanza che contiene i dati sono
HOLIDAYDA DESCRIPTION
--------- --------------------
19-JAN-11 to
17-JAN-11 to
10-JAN-11 new day
Ora voglio il primo giorno lavorativo della settimana. IE:. Se passo "12-Gen-2011" come input, voglio l'O / P da 11-GEN-2011 come il giorno prima business perché 10-Gen-2011 è festa ??p>
Ecco il mio codice:
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;
ho compilato il programma di cui sopra, ma con " Procedura creato con errori di compilazione ".
Nuovo Aggiunti: errori compliation:
LINE/COL ERROR
-------- -----------------------------------------------------------------
9/1 PL/SQL: SQL Statement ignored
9/33 PL/SQL: ORA-00933: SQL command not properly ended
Errore :
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
uno può dirmi il motivo per l'errore? se possibile, tell me la soluzione?
Soluzione
"ho compilato il programma di cui sopra, ma con
Procedure created with compilation errors
"
Se si utilizza un IDE come TOAD o SQL Developer sarebbe mostrare gli errori di compilazione automatica. In caso contrario, essi sono accessibili in SQL * Plus utilizzando questo comando:
SQL> show errors
Ci sono viste anche come USER_ERRORS cui possiamo interrogare.
Il problema è più probabile che l'istruzione SELECT, come la clausola INTO dovrebbe seguire subito dopo la proiezione:
select holidaydate
into l_dHolidayDate
from holiday
where holidaydate = l_dStartDay + i);
Intendiamoci, questo sembra anche sbagliato:
select trunc(to_date(sysdate),'Day')
SYSDATE è già una data, anche se le versioni più recenti di Oracle tendono ad essere più indulgente di utilizzare TO_DATE su una colonna DATE. Quando troncando l'elemento tempo da una data non è necessario includere una maschera di formato come questo è il comportamento di default:
trunc(some_date_variable)
Abbiamo solo bisogno di includere una maschera, se (ad esempio) vogliamo il primo giorno del mese:
trunc(some_date_variable, 'MON')
Se si vuole trovare il primo giorno della settimana, questo lo farà:
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>
Si noti che il primo giorno della settimana dipende dalla impostazione territorio. In alcuni territori il primo giorno della settimana è un giorno lavorativo (per esempio Lunedi nel Regno Unito), in altri non è (Domenica è il giorno 1 negli Stati Uniti). Così può essere necessario aggiungere un offset.
Una volta a risolvere gli errori di compilazione troverete soem runtime errori, probabilmente in materia di eccezioni non gestite NO_DATA_FOUND. Questo perché la query di ricerca non restituirà NULL quando non trova un record corrispondente, fallirà.
Questa è una procedura semplice. Si utilizza una soluzione SQL, SQL, perché è il modo più efficiente di fare le cose. La query interna utilizza il CONNECT BY trucco per generare un set di risultati di date. Questo viene poi ridotta dall'operatore insieme MINUS, che filtrerà eventuali vacanze nella gamma di quella settimana. Infine, la query esterna restituisce la prima data dalla query.
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;
/
Dato questo dati di test (che riflette lo stato bizantina di giorni festivi britannici) ...
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>
... ecco la procedura in azione:
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>
Per inciso, questo è molto cattiva pratica:
PLS-00905: object SYSTEM.SAMPLE is invalid
Non utilizzare il built-in SYS o sistema contabile per il proprio lavoro. Non è troppo grande la possibilità di rompere qualcosa. Creare un nuovo account utente, invece.
Altri suggerimenti
Sto indovinando che la linea
where holidaydate = l_dStartDay + i);
è sbagliato in quanto ha una )
dove non dovrebbe essere.
A parte gli errori già accennato, provare a rimuovere la clausola 'EXIT' come questo ciclo sarà iterare un numero fisso di volte. Inoltre, provare a specificare il nome del blocco in cui termina il blocco come di seguito:
LOOP
...
END LOOP;
END ObjectName;
Dove NomeOggetto è il tuo programma di alto livello. Qui, sarebbe 'campione', così:
LOOP
...
END LOOP;
END sample;