PL/SQL: can't insert into a temporary tables - oracle

I'm not really sure whats wrong with this error. The error occurred at the INSERT INTO statement below. I was trying to insert the values from the cursor loop above into a temporary table. The error was 'SQL Statement ignored'
PROCEDURE loopHalfHourIntervals AS
sourceDay DATE;
sourceDayName VARCHAR2(10);
sourceInterval NUMBER(3);
sourceVolume FLOAT(20);
CURSOR c_findValues IS
SELECT DAY, hh, volume
FROM V_NEM_RM16;
BEGIN
--FOR r_findValues IN c_findValues
OPEN c_findValues;
LOOP
FETCH c_findValues INTO sourceDay, sourceInterval, sourceVolume;
IF identifyHoliday(sourceDay) = TRUE
THEN sourceDayName := 'HOLIDAY';
ELSE sourceDayName := trim(to_char(to_date(sourceDay, 'DD-MON-YYYY'),'day'));
END IF;
INSERT INTO tmpForecast --error occurred here
(
currentDay,
dayInterval,
volume
)
VALUES
(
UPPPER(sourceDayName),
sourceInterval,
sourceVolume
);
EXIT WHEN c_findValues%notfound;
END LOOP;
common.log('Holidays check completed and stored in tmp_forecast');
END loopHalfHourIntervals; ```

Related

No data found in oracle

I have a procedure in oracle that looks like this
create or replace procedure check_display_stock as
id_brg number(20);
rowcount number (20);
begin
-- 1. insert datas from display into temp_display
insert into temp_display
select id_barang,stok,min_stok
from display
where stok <= min_stok;
--2. select the number of datas in temp_display
select count(rownum)
into rowcount
from temp_display;
while(rowcount != 0)
loop
-- Error: no data found
select id_barang
into id_brg
from temp_display
where rownum = 1;
--just another procedure to do other things
insert_spb(id_brg);
delete from temp_display where rownum = 1;
end if;
end loop;
end check_display_stock;
An error occurs when I tried to select into that says no data found.
I don't understand why this happened.
You never decrement rowcount so you will end up deleting the rows in temp_display one-by-one and then keep going (potentially forever) and on the next iteration after you have already emptied the table you will try to select id_barang into id_brg ... and it will fail as you have already emptied the table.
Instead, you could use BULK COLLECT INTO or a CURSOR to bypass the temporary table:
create or replace procedure check_display_stock
as
begin
FOR cur IN ( select id_barang,
stok,
min_stok
from display
where stok <= min_stok
)
LOOP
insert_spb(cur.id_barang);
END LOOP;
END;
/
db<>fiddle here

Ignore lines that causes errors

I have a big Oracle script with thousands of package call inside a BEGIN - END;
Is there a way to ignore the lines that causes error and continue executing the next lines? Some sort of "On Error Resume Next" in vb.
If you have only one BEGIN END section, then you can use EXCEPTION WHEN OTHERS THEN NULL.
SQL> declare
v_var pls_integer;
begin
select 1 into v_var from dual;
-- now error
select 'A' into v_var from dual;
exception when others then null;
end;
SQL> /
PL/SQL procedure successfully completed.
SQL> declare
v_var pls_integer;
begin
select 1 into v_var from dual;
-- now error
select 'A' into v_var from dual;
--exception when others then null;
end;
/
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 6
SQL>
The whole concept of "ignore errors" is a bug, and a lie if any errors occur. That is not to say you cannot trap errors and continue processing, just that you MUST handle the errors. For example, assume the use case: "Data has been loaded into a stage table from multiple .csv files. Now load into the tables A and Table B according to ....".
create procedure
Load_Tables_A_B_from_Stage(process_message out varchar2)
is
Begin
For rec in (select * from stage)
loop
begin
insert into table_a (col1, col2)
values (rec.col_a1, col_a2);
insert into table_b (col1, col2)
values (rec.col_b1, col_b2);
exception
when others then null;
end;
end loop;
process_message := 'Load Tables A,B Complete';
end ;
Now suppose a user created the a .csv file entered "n/a" in numeric columns where there was no value or the value was unknown. The result of this all too common occurrence is all such rows were not loaded, but you have no way to know that until the user complains their data was not loaded even though you told them it was. Further you have no way of determining the problem.
A much better approach is to "capture and report".
create procedure
Load_Tables_A_B_from_Stage(process_message out varchar2)
is
load_error_occurred boolean := False;
Begin
For rec in (select * from stage)
loop
begin
insert into table_a (col1, col2)
values (rec.col_a1, rec.col_a2);
exception
when others then
log_load_error('Load_Tables_A_B_from_Stage', stage_id, sqlerrm);
load_error_occurred := True;
end;
begin
insert into table_b (col1, col2)
values (rec.col_b1, rec.col_b2);
exception
when others then
log_load_error('Load_Tables_A_B_from_Stage', stage_id, sqlerrm);
load_error_occurred := True;
end;
end loop;
if load_error_occurred then
process_message := 'Load Tables A,B Complete: Error(s) Detected';
else
process_message := 'Load Tables A,B Complete: Successful No Error(s)';
end if;
end Load_Tables_A_B_from_Stage ;
Now you have informed the user of the actual status, and where you are contacted you can readily identify the issue.
User here is used in the most general sense. It could mean a calling routine instead of an individual. Point is you do not have to terminate your process due to errors but DO NOT ignore them.
I don't think there is any magic one-liner that will solve this.
As others have, use a editor to automate the wrapping of each call within a BEGIN-EXCEPTION-END block might be quicker/easier.
But, if feel a little adventurous, or try this strategy:
Let's assume you have this:
BEGIN
proc1;
proc2;
proc3;
.
.
.
proc1000;
END;
You could try this (untested, uncompiled but might give you an idea of what to try):
DECLARE
l_progress NUMBER := 0;
l_proc_no NUMBER := 0;
e_proc_err EXCEPTION;
-- A 'runner' procedure than manegrs the counters and runs/skips dpending on these vals
PROCEDURE run_proc ( pname IN VARCHAR2 ) IS
BEGIN
l_proc_no := l_proc_no + 1;
IF l_proc_no >= l_progress
THEN
-- log 'Running pname'
EXECUTE IMMEDIATE 'BEGIN ' || pname || '; END;' ;
l_progress := l_progress + 1;
ELSE
-- log 'Skipping pname'
END IF;
EXCEPTION
WHEN OTHERS THEN
-- log 'Error in pname'
l_progress := l_progress + 1;
RAISE e_proc_err;
END;
BEGIN
l_progress := 0;
<<start>>
l_proc_no := 0;
run_proc ( 'proc1' );
run_proc ( 'proc2' );
run_proc ( 'proc3' );
.
.
run_proc ( 'proc1000' );
EXCEPTION
WHEN e_proc_err THEN
GOTO start;
WHEN OTHERS THEN
RAISE;
END;
The idea here is to add a 'runner' procedure to execute each procedure dynamically and log the run, skip, error.
We maintain a global count of the current process number (l_proc_no) and overall count of steps executed (l_progress).
When an error occurs we log it, raise it and let it fall into the outer blocks EXCEPTION handler where it will restart via an (evil) GOTO.
The GOTO is placed such that the overall execution count is unchanged but the process number is reset to 0.
Now when the run_proc is called it sees that l_progress is greater than l_proc_no, and skips it.
Why is this better than simply wrapping a BEGIN EXCEPTION END around each call?
It might not be, but you make a smaller change to each line of code, and you standardise the logging around each call more neatly.
The danger is a potential infinite loop which is why I specify e_proc_err to denote errors within the called procedures. But it might need tweaking to make it robust.

PL/SQL exception handling - log errors

How do I record the oracle error in a pl/sql script? I have been to the oracle error handling documentation and I see the built in exceptions, but what if I do not know what the exception is? How can I log this in an exception block?
I want to do something like the below.
exception
when others then DBMS_OUTPUT.PUT_LINE(the error)
It's easier to create error logging database trigger with conditional logging, for example my actual error_logging trigger: https://github.com/xtender/xt_scripts/blob/master/error_logging/on_database.sql
create table ERROR_LOG
(
id NUMBER,
username VARCHAR2(30),
errcode INTEGER,
seq INTEGER,
tmstmp TIMESTAMP(6),
msg VARCHAR2(4000),
sql_text CLOB
)
/
create sequence err_seq
/
create or replace trigger trg_error_logging
after servererror
on database
disable
declare
v_id number := err_seq.nextval();
v_tmstmp timestamp:= systimestamp;
n int;
sql_text dbms_standard.ora_name_list_t;
v_sql_text clob;
begin
-- only if plsql_debug is set to TRUE:
for r in (select * from v$parameter p where p.name='plsql_debug' and upper(p.value)='TRUE') loop
v_sql_text:=null;
n := ora_sql_txt(sql_text);
for i in 1..n loop
v_sql_text := v_sql_text || sql_text(i);
end loop;
for i in 1.. ora_server_error_depth
loop
if i=1 then
insert into error_log(id,seq,tmstmp,username,errcode,msg,sql_text)
values( v_id, i, v_tmstmp, user, ora_server_error(i), ora_server_error_msg(i), v_sql_text);
else
insert into error_log(id,seq,tmstmp,username,errcode,msg)
values( v_id, i, v_tmstmp, user, ora_server_error(i), ora_server_error_msg(i) );
end if;
end loop;
commit;
end loop;
END;
/
select object_name,object_type,status from user_objects o where object_name='TRG_ERROR_LOGGING'
/
alter trigger trg_error_logging enable
/
As you can see it logs all errors into the table ERROR_LOG, but only if session parameter plsql_debug is set to true. Obviously, you can change it to own parameters or conditions.

inserting data select into with loop in plsql

I am just want to enter forms detail column data into a database column from a detail block and that must check first entered data which it already have in that column when i entered data data saves in other tables but in token_staus is not entering data and message me No data found for that i write a loop which is not working for me i am making some kind of mistake obviously but not sure where it is
DECLARE
TOKEN_NO NUMBER;
TOKEN_STATUS1 NUMBER;
--TOKEN_STATUS2 := :TOKEN_STATUS;
BEGIN
SELECT SR_NO, TOKEN_STATUS INTO TOKEN_NO, TOKEN_STATUS1 FROM LOOPT2 WHERE SR_NO = :TOKEN_NO;
--IF :TOKEN_STATUS IS NULL
--THEN
LOOP
GO_BLOCK('TOKEN_REC2');
FIRST_RECORD;
INSERT INTO LOOPT2(TOKEN_STATUS) VALUES(:TOKEN_STATUS);
NEXT_RECORD;
EXIT WHEN :SYSTEM.LAST_RECORD = 'TRUE';
END LOOP;
--END IF;
EXCEPTION
when others then
message (sqlerrm);
END;
Please help me
Little Foot please
If I understood you correctly, it would be something like this (check comments within the code): key thing here seems to be a BEGIN-EXCEPTION-END block within the LOOP.
DECLARE
TOKEN_NO NUMBER;
TOKEN_STATUS1 NUMBER;
BEGIN
GO_BLOCK('TOKEN_REC2');
FIRST_RECORD;
LOOP
BEGIN
SELECT SR_NO, TOKEN_STATUS
INTO TOKEN_NO, TOKEN_STATUS1
FROM LOOPT2
WHERE SR_NO = :TOKEN_NO;
-- if such a :TOKEN_NO exists, that SELECT will return some values
-- which means that you want to skip it, so - don't do anything
EXCEPTION
-- if such a :TOKEN_NO does not exist, SELECT will return
-- NO_DATA_FOUND which means that you want to perform insert
WHEN NO_DATA_FOUND THEN
INSERT INTO LOOPT2 (TOKEN_STATUS)
VALUES (:TOKEN_STATUS);
WHEN TOO_MANY_ROWS THEN
NULL;
END;
EXIT WHEN :SYSTEM.LAST_RECORD = 'TRUE';
NEXT_RECORD;
END LOOP;
END;

WHEN-BUTTON-PRESSED trigger raise unhendled exception ORA-01407

I am new in PL SQL and I am trying to resolve problem with copy-past data from .CVS file to database
I create a small application which will take data from .CVS and past it to database.
I create a method, but after I compile it's writtend Successfully compiled
But when I run form I get error
WHEN-BUTTON-PRESSED trigger raise unhendled exception ORA-01407
Does anyone know what this means since I google it and could not find anything ?
I would be very thankfull
declare
import_file text_io.file_type;
import_file_name varchar2(1000);
import_log_file text_io.file_type;
import_log_file_name varchar2(1000);
vec_importovano number;
brojac number;
brojac_redova number;
linebuf varchar2(5000);
p_rbr varchar2(4);
p_polica varchar2(20);
p_banka varchar2 (20);
p_kontakt varchar2(20);
kraj_fajla number;
begin
import_file_name := :Global.Lokacija_prenosa||:import.naziv_fajla||:Global.Ekstenzija_prenosa;
import_file := text_io.fopen(import_file_name,'r');
--p_rbr := 100000;
delete from zivot_trajni_nalog_ponude where banka is not null;
commit;
kraj_fajla := 0;
while kraj_fajla = 0 loop
begin
text_io.get_line(import_file, linebuf);
if brojac_redova>=2 then
if length(linebuf)>100 then
p_rbr:=substr(linebuf, 1, instr(linebuf,';',1,1)-1);
p_polica:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
p_kontakt:=substr(linebuf, instr(linebuf,';',1,3)+1, instr(linebuf,';',1,4) - instr(linebuf,';',1,3)-1);
select count(*)
into vec_importovano
from ZIVOT_TRAJNI_NALOG_PONUDE
where broj_police=p_polica and p_rbr=redni_broj;
if vec_importovano=0 then
insert into ZIVOT_TRAJNI_NALOG_PONUDE values(p_rbr, p_polica, p_banka, p_kontakt);
commit;
end if;
end if;
end if;
EXCEPTION WHEN NO_DATA_FOUND THEN kraj_fajla := 1;
end;
end loop;
update zivot_trajni_nalog_ponude set redni_broj = p_rbr;
commit;
text_io.fclose(import_file);
message('Zavrseno prepisivanje fajla');
end;
The error you got (ORA-01407) means that you are trying to update a column (which is set to NOT NULL) with a NULL value. That won't work. For example:
SQL> create table test (id number not null);
Table created.
SQL> insert into test (id) values (100);
1 row created.
SQL> update test set id = null;
update test set id = null
*
ERROR at line 1:
ORA-01407: cannot update ("SCOTT"."TEST"."ID") to NULL
SQL>
The only UPDATE in your code is this:
UPDATE zivot_trajni_nalog_ponude SET redni_broj = p_rbr;
Apparently, p_rbr is NULL, redni_broj won't accept it and you got the error.
What to do? Debug your code and see why p_rbr doesn't have a value. A simple "solution" might be
IF p_rbr IS NOT NULL
THEN
UPDATE zivot_trajni_nalog_ponude
SET redni_broj = p_rbr;
END IF;
Also, although not related to your problem: don't COMMIT within a loop.
ORA-01407 occurs as you are trying to update/Insert a column to NULL
when the column does not accept NULL values.
To find all the "not null" columns in table ZIVOT_TRAJNI_NALOG_PONUDE, Please check the DDL of the table.

Resources