ORA-06561 while executing PL/SQL procedure - oracle

I have this procedure:
create or replace
PROCEDURE P_P2
IS
v_str varchar2(1000);
v_file_name varchar2(1000);
BEGIN
P_P1(v_str, 'EXPORT_CSV',v_file_name);
v_str := 'select * from H----)';
v_file_name := 'H_'||to_char(sysdate,'DD-MM-YYYY')||'.csv';
END;
I am getting error "ORA-06561: given statement is not supported by package DBMS_SQL" when I execute it:
Error starting at line : 165 in command -
exec P_P1
Error report -
ORA-06561: given statement is not supported by package DBMS_SQL
ORA-06512: at "SYS.DBMS_SQL", line 1120
ORA-06512: at "BIDB.P_P1", line 40
ORA-06512: at "BIDB.P_P2", line 7
ORA-06512: at line 1
06561. 00000 - "given statement is not supported by package DBMS_SQL"
*Cause: Attempting to parse an unsupported statement using procedure
PARSE provided by package DBMS_SQL.
*Action: Only statements which begin with SELECT, DELETE, INSERT, UPDATE,
LOCK, BEGIN, DECLARE or << (PL/SQL label delimiter) are supported.
I cannot see why. What am I doing wrong?

You haven't shown what P_P1 is doing, but from what you have shown, your P_P2 procedure may just be calling it too early; you have a call to P_P1 which uses v_str as a parameter, but it's null at that point - you set it after the call that uses it.
That means that somewhere in P_P1 you are probably ending up doing the equivalent of:
dbms_sql.parse(c, null, dbms_sql.native);
which throws the error you are seeing. You're doing the same with v_filename, which will presumably cause other issues.
So for a start, swap those lines around so the procedure is called last:
create or replace
PROCEDURE P_P2
IS
v_str varchar2(1000);
v_file_name varchar2(1000);
BEGIN
v_str := 'select * from H----)';
v_file_name := 'H_'||to_char(sysdate,'DD-MM-YYYY')||'.csv';
-- call this AFTER populating the variables
P_P1(v_str, 'EXPORT_CSV',v_file_name);
END;
/
You may have other problems of course - the table name looks odd, both because of the dashes and the closing parenthesis; but you may have just hidden the real name oddly. You seem to have changed the procedure names too (though inconsistently, as your exec seems to be calling the wrong one...).

Related

Oracle begin expected got create

I'm writing a PL/SQL program, I've created a procedure and the syntax is correct.
Running this on DataGrip.
`
declare
create or replace procedure salutation(x OUT number) is begin
x:= x*10;
end salutation;
begin
SYS.DBMS_OUTPUT.PUT_LINE('hello');
end;
`
I get error messages when I execute the code:
BEGIN expected, got 'create'.
[2022-12-04 23:58:09] [65000][6550]
[2022-12-04 23:58:09] ORA-06550: line 1, column 7:
[2022-12-04 23:58:09] PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
[2022-12-04 23:58:09] begin function pragma procedure subtype type
[2022-12-04 23:58:09] current cursor delete
[2022-12-04 23:58:09] exists prior
I don't think there's a problem with the syntax.
Also why does the DataGrip not allow DBMS_OUTPUT.PUT_LINE without the SYS. ? even though I've enabled the DBMSOUTPUT.
You can't have static DDL statements (like create procedure) within PL/SQL (you'd need to use dynamic SQL, but it's very rarely necessary anyway).
But if you're trying to declare a local procedure within your anonymous block - not create a permanent, stored procedure, then you don't need the create part:
declare
y number := 42;
procedure salutation(x IN OUT number) is begin
x:= x*10;
end salutation;
begin
SYS.DBMS_OUTPUT.PUT_LINE('hello');
-- call salutation here if you want...
salutation(y);
dbms_output.put_line(to_char(y));
end;
/
1 rows affected
dbms_output:
hello
420
fiddle
Note that I changed the argument to IN OUT - otherwise it would always be reset to null.
If you want to create a permanent stored procedure then do that separately, before you try to run your anonymous block:
create or replace procedure salutation(x IN OUT number) is begin
x:= x*10;
end salutation;
/
declare
y number := 42;
begin
SYS.DBMS_OUTPUT.PUT_LINE('hello');
-- call salutation here if you want...
salutation(y);
dbms_output.put_line(to_char(y));
end;
/
1 rows affected
dbms_output:
hello
420
fiddle
Also why does the DataGrip not allow DBMS_OUTPUT.PUT_LINE without the SYS. ?
That suggests your database is missing a public synonym for the package; not a DataGrip thing, you'd see the same behaviour using any client. You'd need to ask your DBA why it's missing and whether it can be reinstated. (I haven't included the schema prefix in the extra calls I added, but if those don't work for you then you'll need to add it.)

Execute PROCEDURE on Oracle PL/SQL with DECLARE variable

I just currently learning about Oracle PL/SQL. I wanna create store procedure with variable and then call it with another script. Is it possible?
I tried use simple script without variable and it works:
CREATE OR REPLACE PROCEDURE testmyproc AS
BEGIN
INSERT INTO tes_table(dt)
VALUES (sysdate);
commit;
END testmyproc;
Then I call it with another script abc.sql
begin
testmyproc;
end;
It works successfully.
But, unfortunately if I use DECLARE (variable) at my PROCEDURE, it show error when I execute (but it success in create procedure).
Here's my PROCEDURE (no error):
CREATE OR REPLACE PROCEDURE sp_testmyproc AS
DECLARE
job_name varchar(100);
status_key number;
status_desc varchar(100);
notes varchar(250);
BEGIN
status_key := 1;
status_desc := 'SUCCESS';
notes := 'Process Completed';
INSERT INTO automation_log(job_name, dt, status_key, status_desc, notes)
VALUES (job_name, sysdate, status_key, status_desc, notes);
commit;
END sp_testmyproc;
Here's my execure script abc.sql (show error when i execute it)
-without DECLARE
begin
sp_testmyproc;
end;
-I tried to execute it with DECLARE
DECLARE
job_name varchar(100);
status_key number;
status_desc varchar(100);
notes varchar(250);
begin
status_key := 1;
status_desc := 'SUCCESS';
notes := 'Process Completed';
sp_testmyproc;
end;
It show error like this:
> ORA-06550: line 8, column 11:
> PLS-00905: SP_TESTMYPROC is invalid
> ORA-06550: line 8, column 3:
> PL/SQL: Statement ignored
Can I call Procedure for another script? Is It best practice?
I just think PROCEDURE can be used for many cases (something like function in programming).
Thank you!
You need to learn the syntax of the procedure.
In Procedure, You should not use the keyword DECLARE. Any variables you want to declare must be between AS and BEGIN in the procedure.
Your procedure should look like follows:
CREATE OR REPLACE PROCEDURE sp_testmyproc AS
--DECLARE
job_name varchar(100);
status_key number;
status_desc varchar(100);
notes varchar(250);
BEGIN
status_key := 1;
.....
.....
.....
Refer to this document for the syntax of the oracle procedure as it is very easy to follow.
Please note the difference when creating a stored procedure in SQL*Plus:
SQL> create or replace procedure test_ok as
2 v number;
3 begin
4 v:=0;
5 end;
6 /
Procedure created.
SQL> show errors
No errors.
SQL> create or replace procedure test_ko as
2 declare
3 v number;
4 begin
5 v:=0;
6 end;
7 /
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE TEST_KO:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/1 PLS-00103: Encountered the symbol "DECLARE" when expecting one of
the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior external language
SQL>
If you have compilation errors you get at least Warning: Procedure created with compilation errors. If you have compilation errors and use show errors you get all error messages.

Get a value from sql file to the invoking sql file

I have a file1.sql which invokes file2.sql.
file2.sql:
declare
v_stmt varchar2(1000);
begin
v_stmt := 'create index idx on tab1(&1)';
:stmt := v_stmt;
end;
/
file1.sql:
var stmt varchar2(4000);
#file2.sql 'col1'
:stmt;
Executing file1.sql throws the following errors:
SP2-0552: Bind variable "STMT" not declared.
SP2-0042: unknown command ":stmt" - rest of line ignored.
How do I get the value of variable v_stmt in file1.sql?
You can't run arbitrary code from the SQL*Plus command line using a bind variable; the bind variable is relevant to SQL and PL/SQL statements, not natively to SQL*Plus (even though it's declared there with the var).
To execute the statement you'll need to use dynamic SQL, in an anonymous PL/SQL block; so changing file1.sql to:
var stmt varchar2(4000);
#file2.sql 'col1'
begin
execute immediate :stmt;
end;
/
or slightly shorter, but also perhaps slightly confusing::
var stmt varchar2(4000);
#file2.sql 'col1'
exec execute immediate :stmt;
When I run that I see:
SQL> #file1
PL/SQL procedure successfully completed.
begin
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at line 2
which is reasonable as I don't have your tab1 table in my schema. You can see that is trying to execute the statement though; and there is no SP2-0552 error (though I don't see that with your original code either).
You can also use print stmt to see the generated value before it's run (note there is no colon prefix); or you could use dbms_output within the anonymous block, of course.

Execution of Multiple procedures one after another is not working

I am trying to execute a procedure which in turn should execute four other procedures one after the other. How do I acheive this?
Create or replace procedure mainproc
as
begin
tack(400);
phno_insert;
address_insert;
academics_insert;
commit;
end;
Error report:
PLS-00905: Object phno_insert is invalid. PL/SQL: Statement ignored.
PLS-00905: Object address_insert is invalid. PL/SQL: Statement
ignored. PLS-00905: Object academics_insert is invalid. PL/SQL:
Statement ignored.
The problem seems to be in the fact that you have a procedure doing a DDL over an object that is statically referenced in another procedure; for example, if I define:
create table runtimeTable as select 1 as one from dual;
create or replace procedure createTable is
begin
execute immediate 'drop table runtimeTable';
execute immediate 'create table runtimeTable as select 1 as one from dual';
end;
create or replace procedure useTable is
vVar number;
begin
select one
into vVar
from runtimeTable;
--
dbms_output.put_line(vVar);
end;
create or replace procedure createAndUseTable is
begin
createTable;
useTable;
end;
/
when I try to execute createAndUseTable I get:
ORA-04068: existing state of packages has been discarded ORA-04065:
not executed, altered or dropped stored procedure "ALEK.USETABLE"
ORA-06508: PL/SQL: could not find program unit being called:
"ALEK.USETABLE" ORA-06512: at "ALEK.CREATEANDUSETABLE", line 4
ORA-06512: at line 1
If you strictly need to do a DDL runtime, you need to use dynamic SQL to reference the modified object; for example if I define the procedure useTable this way
create or replace procedure useTable is
vVar number;
begin
execute immediate
'select one
from runtimeTable'
into vVar;
--
dbms_output.put_line(vVar);
end;
the call to createAndUseTable will work:
SQL> exec createAndUseTable
1

Using Dynamic SQL With Objects

I have an object and I want to update an object table from with it dynamically. As an example
create or replace type typA as object
(
a number,
member procedure insert_self
);
/
create or replace type body typA is
member procedure insert_self is
begin
null;
end;
end;
/
create table typA_table of typA;
/
create or replace type body typA is
member procedure insert_self is
sql_stmt varchar2(200);
begin
sql_stmt := 'insert into typ_a_table values(self)';
execute immediate sql_stmt;
end;
end;
/
declare
l_typ typA;
begin
l_typ := typA(123);
l_typ.insert_self;
end;
But this returns an error due to the line which specifies 'self' in the sql_stmt.
Error report -
ORA-04063: table "SYSTEM.TYP_A_TABLE" has errors
ORA-06512: at "SYSTEM.TYPA", line 6
ORA-06512: at line 5
04063. 00000 - "%s has errors"
*Cause: Attempt to execute a stored procedure or use a view that has
errors. For stored procedures, the problem could be syntax errors
or references to other, non-existent procedures. For views,
the problem could be a reference in the view's defining query to
a non-existent table.
Can also be a table which has references to non-existent or
inaccessible types.
*Action: Fix the errors and/or create referenced objects as necessary.
Is there anyway to get around this error where I'm referencing variables that aren't easily converted to a string?
Can you not simply change your member procedure to something like the below, seems to work for me.
create or replace type body typA is
member procedure insert_self is
sql_stmt varchar2(200);
begin
insert into typ_a_table values(self.a);
end;
end;

Resources