ORA-21700: object does not exist or is marked for delete - sql

I have package with Period and TableOfPeriod types:
TYPE Period
IS RECORD
( StartPeriod Date,
EndPeriod Date
);
TYPE TableOfPeriod
IS TABLE OF Period;
and in this package I have three simple function:
FUNCTION Temp1
RETURN TableOfPeriod IS
returnedValue TableOfPeriod := TableOfPeriod();
BEGIN
returnedValue.extend(1);
returnedValue(1).StartPeriod := sysdate-100;
returnedValue(1).EndPeriod := sysdate;
RETURN returnedValue;
END Temp1;
FUNCTION CalculateFine
return VARCHAR2
IS
freewillLockTableRP TableOfPeriod:=TableOfPeriod();
compulsoryLockTableRP TableOfPeriod:=TableOfPeriod();
BEGIN
--for testing
compulsoryLockTableRP:=Temp1();
FOR i IN compulsoryLockTableRP.FIRST..compulsoryLockTableRP.LAST LOOP
IF(((compulsoryLockTableRP(i).EndPeriod - compulsoryLockTableRP(i).StartPeriod)>1)) THEN
BEGIN
-- RAISE_APPLICATION_ERROR(-20001, 'Hello world');
SELECT T111.StartPeriod StartPeriod,
T111.EndPeriod EndPeriod
bulk collect into freewillLockTableFull
FROM TABLE(DistributeDaysByPeriods(compulsoryLockTableRP, 5)) T111;
END;
END IF;
END LOOP;
/*SELECT T111.StartPeriod StartPeriod,
T111.EndPeriod EndPeriod
-- BULK COLLECT INTO compulsoryLockTableRP
bulk collect into freewillLockTableFull
FROM TABLE(DistributeDaysByPeriods(compulsoryLockTableRP, 5)) T111;*/
--===========
--SOME OTHER PROCESSING
RETURN 'Ok '
|| '#r';
EXCEPTION
WHEN No_Data_Found THEN return 'No data found#g';
-- WHEN OTHERS THEN RETURN SQLERRM;
END CalculateFine;
When I execute this function, I have next error:
"ORA-21700: object does not exist or is marked for delete ORA-06512:
at "MyPackageName", line 1181 ORA-06512: at line 1
21700. 00000 - "object does not exist or is marked for delete""
where 1181 line is a line with Select statement of CalculateFine function. Can anybody tell me, whats wrong and how I can solve this problem?

Check if you have in the same folder where your package is located a file with the same name but with an extention *.~sql (e.g.: your_file_name.~sql). I had the same error but after I have deleted an *.~sql file I could compile my package without ORA errors.

Related

PL/SQL Function to check whether a number is prime or not

Please find the error and rectify this code
This is a PL/SQL function to check whether a number is prime or not
By using the flag method instead of using count to check the requirement, it's working perfectly but not for this method.
create or replace function isprime(x in number)
RETURN number
IS
i int;
count int;
BEGIN
count:=0;
for i in 2..x/2 LOOP
if mod(x,i)=0 then
count:=count+1;
end if;
end loop;
return count;
end;
/
Warning: Function created with compilation errors.
DECLARE
n int;
c int;
BEGIN
n:=&n;
c:=isprime(n);
if c=0 then
dbms_output.put_line(n||'is a prime number');
else
dbms_output.put_line(n||'is not prime');
end if;
end;
/
Enter value for n: 5
old 5: n:=&n;
new 5: n:=5;
c:=isprime(n);
*
ERROR at line 6:
ORA-06550: line 6, column 4:
PLS-00905: object SYSTEM.ISPRIME is invalid
ORA-06550: line 6, column 1:
PL/SQL: Statement ignored
Here is the error list:
SQL> show errors
Errors for FUNCTION ISPRIME:
LINE/COL ERROR
-------- -----------------------------------------------------------------
10/1 PL/SQL: Statement ignored
10/8 PLS-00204: function or pseudo-column 'COUNT' may be used inside a
SQL statement only
13/1 PL/SQL: Statement ignored
13/8 PLS-00204: function or pseudo-column 'COUNT' may be used inside a
SQL statement only
COUNT is reserve sql word, have a look at this as an alternative solution for this task.
DECLARE
value_ NUMBER default :A;
i NUMBER DEFAULT 5;
is_prime VARCHAR2(5 CHAR);
BEGIN
IF value_ = 2 OR value_ = 3 THEN
is_prime := 'TRUE';
ELSIF MOD(value_,2)=0 OR MOD(value_,3)=0 OR value_ <= 1 THEN
is_prime := 'FALSE';
END IF;
WHILE POWER(i,2) <= value_ LOOP
IF MOD(value_,i)=0 OR MOD(value_,i + 2)=0 THEN
is_prime := 'FALSE';
exit;
END IF;
i := i + 6;
end loop;
is_prime := nvl(is_prime,'TRUE');
DBMS_Output.Put_Line(is_prime||' IT IS '||CASE is_prime WHEN 'FALSE' THEN 'NOT' END||'A PRIME NUMBER');
END;

Error in return of PLSQL ORACLE Not Working

This Code is:
CREATE OR REPLACE
PROCEDURE Actualiza_Saldo(fecha_ini IN DATE, fecha_fin IN DATE) RETURN NUMBER
AS
fechaTemp DATE;
diasTotales NUMBER := fecha_fin- fecha_ini;diasLaborables NUMBER;
sab VARCHAR2(10) := 'SÁBADO';dom VARCHAR2(10) := 'DOMINGO';diasTemp VARCHAR2(10);
BEGIN
diasLaborables:= diastotales;
FOR i IN 0..diasTotales LOOP
fechaTemp := fecha_ini + i;
DBMS_OUTPUT.PUT_LINE(to_char(fechaTemp));
diasTemp := TO_CHAR(fechaTemp, 'DAY', 'NLS_DATE_LANGUAGE=SPANISH');
IF (TRIM(diasTemp)=sab or TRIM(diasTemp)=dom) THEN
diaslaborables := diaslaborables-1;
END IF;
END LOOP;
dbms_output.put_line(diaslaborables);
RETURN diasLaborables;
END Actualiza_Saldo;
If I execute without returning it works, if I try to return a value it fails, I do not know what could be happening.
The error of oracle is:
Warning: la ejecución ha terminado con advertencias
PROCEDURE Actualiza_Saldo(fecha_ini Compilado.
Error que empieza en la línea 1 del comando:
EXEC Actualiza_Saldo();
Informe de error:
ORA-06550: línea 1, columna 7:
PLS-00905: el objeto HR.ACTUALIZA_SALDO no es válido
ORA-06550: línea 1, columna 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The code with constant value:
CREATE OR REPLACE
PROCEDURE Actualiza_Saldo(fecha_ini IN DATE DEFAULT '10/08/2018', fecha_fin IN DATE DEFAULT '30/08/2018')
AS
fechaTemp DATE;
diasTotales NUMBER := fecha_fin- fecha_ini;diasLaborables NUMBER;
sab VARCHAR2(10) := 'SÁBADO';dom VARCHAR2(10) := 'DOMINGO';diasTemp VARCHAR2(10);
BEGIN
diasLaborables:= diastotales;
FOR i IN 0..diasTotales LOOP
fechaTemp := fecha_ini + i;
DBMS_OUTPUT.PUT_LINE(to_char(fechaTemp));
diasTemp := TO_CHAR(fechaTemp, 'DAY', 'NLS_DATE_LANGUAGE=SPANISH');
IF (TRIM(diasTemp)=sab or TRIM(diasTemp)=dom) THEN
diaslaborables := diaslaborables-1;
END IF;
END LOOP;
dbms_output.put_line(diaslaborables);
END Actualiza_Saldo;
EXEC Actualiza_Saldo();
And the exit of the code without the returns and the test values ​​is a route from the start date and the final date subtracting the days Saturday and Sunday.
PROCEDURE Actualiza_Saldo(fecha_ini Compilado.
anonymous block completed
10/08/18
11/08/18
12/08/18
13/08/18
14/08/18
15/08/18
16/08/18
17/08/18
18/08/18
19/08/18
20/08/18
21/08/18
22/08/18
23/08/18
24/08/18
25/08/18
26/08/18
27/08/18
28/08/18
29/08/18
30/08/18
14
But if I try to return the value the algorithm dies.
I have no idea what I am doing wrong or where is the fault, if you could help me I would greatly appreciate it.
Procedures cannot return a value, in Oracle, You can have out-parameters which would be visible after the procedure runs.
But here is another option you can try, instead of writing code to generate dates between two, try to do it using a single select query and open a out cursor to have the values populated after the proc completes
An example as follows
create or replace procedure generate_dates(start_date in date, end_date in date, result_set out sys_refcursor)
as
begin
open result_set for
select trunc(start_date)+level as output_dates
from dual
connect by level<=trunc(end_date)-trunc(start_date);
end;
if you are using sqlplus to connect to your database
you would call the proc as follows
var x refcursor
begin
generate_dates(date '2018-01-01',date '2018-12-31',:x);
end;
print x;
My mistake was that I was not doing a function but a procedure solved.
CREATE OR REPLACE
FUNCTION HR.Actualiza_Saldo(fecha_ini IN DATE/* DEFAULT '10/08/2018'*/, fecha_fin IN DATE/* DEFAULT '30/08/2018'*/) RETURN NUMBER
AS

ORA-06512: at "SYS.UTL_FILE", line 536

We're getting the following error in an SQL procedure on Ubuntu. The same procedure is executing properly on Windows. The goal of the procedure is to import a .csv file into an external oracle table.
The Oracle error:
ORA-29283: invalid file operation ORA-06512: at "SYS.UTL_FILE", line 536 ORA-29283: invalid file operation
This SO question might have been a solution, but even after giving proper permissions chmod 777 (which solved the issue in that case) to the files concerned we are facing the same error.
ORA-29283: invalid file operation ORA-06512: at "SYS.UTL_FILE", line 536
The concerned portion of the procedure is :
for i in c loop
dbms_output.put_line('Inside for loop');
select count(file_name) into f_n from t_filenames_exp e where i.file_name=e.file_name;
if f_n=0 then
dbms_output.put_line('Inside if statement');
insert into t_filenames_exp(file_name,status) values(i.file_name,'need_to_read');
select f_id into f_idn from t_filenames_exp e where e.file_name=i.file_name;
select substr(i.file_name,instr(i.file_name,'exp_'),4) into fchk from dual;
select to_char(to_date(to_char(SEQ_DATE,'dd-MON-yyyy'),'dd-MON-yyyy'),'D') into v_sufix from M_LAB_ID_SEQ_TAB;
if(fchk='exp_') then
file_handle := UTL_FILE.FOPEN('EXP_DATA',i.file_name,'R');
file_handle1 := UTL_FILE.FOPEN('EXP','staging.txt','W');
loop
begin
utl_file.get_line(file_handle,output_line);
utl_file.put_line(file_handle1,output_line);
exception when no_data_found then
exit;
end;
end loop;
if utl_file.is_open(file_handle) then
utl_file.fclose(file_handle);
end if;
if utl_file.is_open(file_handle1) then
utl_file.fclose(file_handle1);
end if;
/*insert into t_files_data_exp(f_id,patient_last_name,patient_name,patient_id_code,method_internal_index,method_acronym,index_repeat,result,unit_of_measurement,minimum_reference_value,maximum_reference_value,date_)
select f_idn,patient_last_name,patient_name,(patient_id_code ||'H'||v_sufix),method_internal_index,method_acronym,index_repeat,result, unit_of_measurement,minimum_reference_value,maximum_reference_value,date_ from files_data;*/
insert into t_files_data_exp(f_id,patient_last_name,patient_name,patient_id_code,method_internal_index,method_acronym,index_repeat,result,unit_of_measurement,minimum_reference_value,maximum_reference_value,date_)
select f_idn,'Unknown','Unknown',(r.patient_id_code ||'H'||v_sufix),m.CANONICAL_ID,r.METHOD_ACRONYM,0,r.RESULT,r.unit_of_measurement,'','','' from files_data r ,M_METHODS_EXP m where m.METHOD_ACRONYM=r.METHOD_ACRONYM;
else
file_handle := UTL_FILE.FOPEN('EXP_DATA',i.file_name,'R');
file_handle1 := UTL_FILE.FOPEN('EXP','staging1.txt','W');
loop
begin
utl_file.get_line(file_handle,output_line);
utl_file.put_line(file_handle1,output_line);
exception when no_data_found then
exit;
end;
end loop;
if utl_file.is_open(file_handle) then
utl_file.fclose(file_handle);
end if;
if utl_file.is_open(file_handle1) then
utl_file.fclose(file_handle1);
end if;
insert into t_files_data_exp(f_id,patient_last_name,patient_name,patient_id_code,method_internal_index,method_acronym,index_repeat,result,unit_of_measurement,minimum_reference_value,maximum_reference_value,date_)
select f_idn,'Unknown','Unknown',r.PATIENT_ID_CODE,m.CANONICAL_ID,r.METHOD_ACRONYM,0,r.RESULT,r.unit_of_measurement,'','','' from rfiles_data r ,M_METHODS_EXP m where m.METHOD_ACRONYM=r.METHOD_ACRONYM;
end if;
-- Check whether the data in csv file is same as data in external table.
if trace='on' then
if(fchk='expr_') then
dbms_output.put_line('**************************************************');
select i.file_name,count(*) into filename,rows_in_file from files_data;
dbms_output.put_line('File name :'||filename);
dbms_output.put_line('Total no of rows :'||rows_in_file);
select replace(filename,'exp','_exp') into new_filename from dual;
file_handle2 := UTL_FILE.FOPEN('EXP_LOG',new_filename,'W');
for i1 in cur loop
/*data:=to_char (i1.patient_last_name||';'||i1.patient_name||';'||i1.patient_id_code||';'||i1.method_internal_index||';'||i1.method_acronym||';'||i1.index_repeat||';'||i1.result||';'||i1.unit_of_measurement||';'||i1.minimum_reference_value||';'||i1.maximum_reference_value||';'||i1.date_);*/
data:=to_char(i1.patient_id_code||';'||i1.method_acronym||';'||i1.result||';'||i1.unit_of_measurement);
utl_file.put_line(file_handle2,data);
end loop;
else
dbms_output.put_line('**************************************************');
select i.file_name,count(*) into filename,rows_in_file from rfiles_data;
dbms_output.put_line('File name :'||filename);
dbms_output.put_line('Total no of rows :'||rows_in_file);
select replace(filename,'expr','_expr') into new_filename from dual;
file_handle2 := UTL_FILE.FOPEN('EXP_LOG',new_filename,'W');
for i1 in cur1 loop
/*data:=to_char (i1.m_id||';'||i1.date_||';'||i1.METHOD_ACRONYM||';'||i1.PATIENT_ID_CODE||';'||i1.TEST_TYPE||';'||i1.UNIT_OF_MEASUREMENT||';'||i1.RESULT||';'||i1.RESULT_FLAG); */
data:=to_char(i1.patient_id_code||';'||i1.method_acronym||';'||i1.result||';'||i1.unit_of_measurement);
utl_file.put_line(file_handle2,data);
end loop;
end if;
if utl_file.is_open(file_handle2) then
utl_file.fclose(file_handle2);
end if;
dbms_output.put_line('*************************************************');
end if;
end if;
end loop;
The line on which the error is occurring is:
file_handle := UTL_FILE.FOPEN('EXP_DATA',i.file_name,'R');
The permissions given to the file is as follows:
-rwxrwxrwx 1 rama rama 240 Feb 26 11:24 exp_41_02_2016.csv`
How to trace the problem which is causing this issue?
Please let me know if you want any other information?
It's an o/s file error...likely from permissions. The owner of the database shadow process that is executing the package is the o/s owner that needs permissions -- that's probably 'oracle'. You can test by logging in as 'oracle' on the database server and see if you can read the file in question. #alex poole offers a great thought to check the permissions of all parent directories.

Invalid Identifier When Trying to Use Package Function in Summation Expression

I'm trying to use the sum function with a package function but running into an "invalid identifier" bug. Here's some example code with the error causing function commented
create or replace type numType as object
(
myNum number
)
;
/
create or replace type numTypes is table of numType;
/
create or replace package testNumberPackage as
function ReturnNum(in_numType numType) return number;
end;
/
create or replace package body testNumberPackage as
function ReturnNum(in_numType numType) return number is
begin
return in_numType.myNum;
end;
end;
/
declare l_numTypes numTypes;
l_count number;
begin
l_numTypes := numTypes();
for i in 1 .. 100 loop
l_numTypes.extend(1);
l_numTypes(l_numTypes.last) := numType(i);
end loop;
select sum(n.myNum) into l_count from table(l_numTypes) n;
select sum(testNumberPackage.ReturnNum(n)) into l_count from table(l_numTypes) n; --causes the error
dbms_output.put_line(l_count);
end;
/
The exact error for this code is
ORA-06550: line 11, column 42
PL/SQL: ORA-00904: "N": invalid identifier
ORA-6550: line 11, column 3:
PL/SQL: SQL Statement ignored
Thanks for any help.
The first issue is that you can't pass a table into a parameter by using its alias. It doesn't even make sense to try doing that.
The next issue is how to get the column mynum that is returned from the table(l_numTypes) into the correct format to pass into testNumberPackage.ReturnNum, since it's of NUMBER datatype, and the function is expecting a numtype parameter.
To do that, you need to pass in an object with that column, like so: numtype(n.mynum).
The following works for me:
declare
l_numTypes numTypes;
l_count number;
begin
l_numTypes := numTypes();
for i in 1 .. 100 loop
l_numTypes.extend(1);
l_numTypes(l_numTypes.last) := numType(i);
end loop;
select sum(n.myNum) into l_count from table(l_numTypes) n;
select sum(testNumberPackage.ReturnNum(numtype(n.mynum))) into l_count from table(l_numTypes) n; --causes the error
dbms_output.put_line(l_count);
end;
/
5050
Clear as mud?

raise_application_error exception handling in subprocedures

I have multiple stored procedures calling multiple stored procedures in my database. To give a small example, I've constructed a fictionalised version of a few of them below. In my example, a Java program calls calculate_bill, which calls calculate_commission, which calls update_record.
I'm hoping to get some advice on how best to propagate the error messages up the stack to the calling Java layer, so the user gets a precise error message corresponding to wherever the error has occurred.
I'm really quite stuck on this. I've played around in my example with raise_application_error and just continually shuffling it up the stack. Is the way I'm doing it below remotely correct? Or is one raise_application_error in the relevant procedure enough, with no pragma exception init etc needed?
To give an idea of what I mean, in the example below, if a user entered a number which corresponded to a record which couldn't be updated because it didn't exist, I'd like them to get the message:
"Error calculating bill. Error calculating commission. No record exists to be updated" or something to that effect.
So two questions:
What is the best practice, most efficient, most tidy way to pass error messages up the stack for the end user in the application layer?
Does anyone have any suggestions on tidier output from the code, i.e. the best way to concatenate these errors to make them more meaningful? I'm really open to any suggestions on how to make this work best as I have absolutely no prior experience in this.
Example:
(Error in code):
-20000 : Error in top level procedure
-20001 : Error in middle level procedure
-20002 : Error in bottom level procedure
Java code:
try {
// call calculate_bill
exception (SQLException ex)
// output oracle code and relevant message.
Oracle code:
create or replace procedure calculate_bill(in_num NUMBER)
is
error_calculating_commission EXCEPTION;
error_updating_record EXCEPTION;
PRAGMA EXCEPTION_INIT (error_calculating_commission, -20001);
PRAGMA EXCEPTION_INIT (error_updating_record , -20002);
begin
if in_num > 2 then
calculate_commission(in_num);
else
raise_application_error(-20000, 'Error calculating bill. ' || 'Record number doesn''t exist.', false);
end if;
exception
when error_calculating_commission then
raise_application_error(SQLCODE, 'Error calculating bill. ' || SQLERRM, false);
when error_updating_record then
raise_application_error(SQLCODE, 'Error calculating bill. ' || SQLERRM, false);
when others then
raise_application_error(-20000, 'Unknown error encountered calculating bill.', false);
end;
create or replace procedure calculate_commission(in_num NUMBER)
is
begin
if in_num < 30 then
raise_application_error(-20001, 'Number too small to calculate commission.', false);
elsif in_num >= 30 and < 40 then
declare
error_storing_record EXCEPTION;
PRAGMA EXCEPTION_INIT (error_storing_record , -20002);
begin
update_record(in_num);
exception
when error_storing_record then
raise_application_error(SQLCODE, 'Error calculating commission. ' || SQLERRM, false);
when others then
raise_application_error(-20001, 'Unknown error encountered calculating commission.', false);
else
raise_application_error(-20001, 'Number too large to calculate commission', false);
end if;
end;
create or replace procedure update_record(in_num NUMBER)
is
begin
//some SQL query with a where clause, where in_num equals something
exception
when no_data_found then
raise_application_error(-20002, 'No record exists to be updated', false);
when others then
raise_application_error(-20002, 'Unknown error encountered updating record.', false);
end if;
end;
Note: I know this example is a little contrived. I was just trying to keep it brief.
The way I would implement this is to use RAISE_APPLICATION_ERROR where the error actually originates, then leave it unhandled in the other layers (or, if you want to do logging in the database, catch it in the OTHERS section, then re-raise using RAISE rather than RAISE_APPLICATION_ERROR.
You're OTHERS sections are still perpetuating the problem raised in your previous question: when an unknown error occurs you're replacing it with a generic, unhelpful message. To paraphrase Tom Kyte, "a WHEN OTHERS that does not end in RAISE is a bug`.
With no logging in the database, I would re-write the provided code like this:
create or replace procedure calculate_bill(in_num NUMBER)
is
begin
if in_num > 2 then
calculate_commission(in_num);
else
raise_application_error(-20000, 'Error calculating bill. ' || 'Record number doesn''t exist.', false);
end if;
end;
create or replace procedure calculate_commission(in_num NUMBER)
is
begin
if in_num < 30 then
raise_application_error(-20001, 'Number too small to calculate commission.', false);
elsif in_num >= 30 and in_num < 40 then
update_record(in_num);
else
raise_application_error(-20001, 'Number too large to calculate commission', false);
end if;
end;
create or replace procedure update_record(in_num NUMBER)
is
v_stub number;
begin
select 1 into v_stub from dual where 1 = 0;
exception
when no_data_found then
raise_application_error(-20002, 'No record exists to be updated', false);
end;
Below is sample input and the stack traces they created:
exec calculate_bill(0)
ORA-20000: Error calculating bill. Record number doesn't exist.
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 7
ORA-06512: at line 1
exec calculate_bill(10)
ORA-20001: Number too small to calculate commission.
ORA-06512: at "SCHEMANAME.CALCULATE_COMMISSION", line 5
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 5
ORA-06512: at line 1
exec calculate_bill(35)
ORA-20002: No record exists to be updated
ORA-06512: at "SCHEMANAME.UPDATE_RECORD", line 8
ORA-06512: at "SCHEMANAME.CALCULATE_COMMISSION", line 7
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 5
ORA-06512: at line 1
exec calculate_bill(100)
ORA-20001: Number too large to calculate commission
ORA-06512: at "SCHEMANAME.CALCULATE_COMMISSION", line 9
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 5
ORA-06512: at line 1
If you were to add error logging to these procedures, it would be a simple matter of adding an OTHERS clause to the EXCEPTION sections:
WHEN OTHERS THEN
my_logging (SQLCODE, SQLERRM, DBMS_UTILITY.format_error_backtrace ());
RAISE;
The new exception created by your RAISE_APPLICATION_ERROR calls will be handled transparently by the RAISE.