ORA-00900: invalid SQL statement - Call procedure inside another - oracle

I create procedure which call procedure inside another. I have an error ORA-00900: invalid SQL statement.
CREATE OR REPLACE PROCEDURE AP_MOVE_OUT
is
BEGIN
EXECUTE IMMEDIATE 'AP_MOVEOUT_COUNT(''GNW-M2'',to_date(''2020-11-02'',''yyyy-MM-dd''),to_date(''2020-11-06'',''yyyy-MM-dd''),''ast'');';
END;
/
Procedure compiled without any error, but when I run it:
BEGIN
AP_MOVE_OUT;
END;
/
I've got an error: ORA-00900: invalid SQL statement
ORA-06512: at "DEVUSER.AP_MOVE", line 4
ORA-06512: at line 2
00900. 00000 - "invalid SQL statement"
When I execute procedure AP_MOVEOUT_COUNT outside procedure AP_MOVE_OUT it works correctly, so I can't find the reason of these error. Here is the example that works for me outside procedure AP_MOVE_OUT:
EXEC AT_MOVEOUT_COUNT('GNW-M2',to_date('2020-11-02','yyyy-MM-dd'),to_date('2020-11-06','yyyy-MM-dd'),'ast');

Expression called by execute immediate should be a valid sql or pl/sql statement. In your case the statement is not complete. Transforming it to a complete anonymous pl/sql block should solve the problem.
create or replace procedure AP_MOVE_OUT
is
BEGIN
execute immediate 'begin AP_MOVEOUT_COUNT(''GNW-M2'',to_date(''2020-11-02'',''yyyy-MM-dd''),to_date(''2020-11-06'',''yyyy-MM-dd''),''ast''); end;';
END;
See also simple example on fiddle
Also consider using bind variables instead of concatenating values into the code.

You don't need to use EXECUTE IMMEDIATE to call a stored procedure from another. You also don't use EXEC or any other keyword.
You've said that
exec AT_MOVEOUT_COUNT('GNW-M2',to_date('2020-11-02','yyyy-MM-dd'),to_date('2020-11-06','yyyy-MM-dd'),'ast');
works, so I would expect the following procedure to work too:
create or replace procedure AP_MOVE_OUT
is
BEGIN
AT_MOVEOUT_COUNT('GNW-M2',to_date('2020-11-02','yyyy-MM-dd'),to_date('2020-11-06','yyyy-MM-dd'),'ast');
END;

Related

calling stored procedure with cursor and out parameter

I have the following stored procedure
CREATE OR Replace PROCEDURE sprocvPOP_GetvemployeeByFilter
(TheFilter varchar2,
TheOrder varchar2,
PageOrder int,
ItemsPerPage int,
TheCount out number,
cur out sys_refcursor)as
begin
........
end
I want to call this procedure, and print cur parameter and the count parameter values because they are out variables.
I tried using the following syntax in SQL Developer
set serveroutput on
var rc refcursor;
declare
mycount number(19);
begin
execute sprocvPOP_GetvemployeeByFilter (NULL,NULL,1,10,mycount,:rc);
print rc;
dbms_output.put_line(mycount);
end;
but I got the error
PLS-00103: Encountered the symbol "RC" when expecting one of the following:
:= . ( # % ;
The symbol ":=" was substituted for "RC" to continue.
How can I execute this procedure and print out parameters in SQL Developer?
To answer your original question, print rc is a SQL*Plus command, so it needs to be outside the PL/SQL block. execute is also a SQL*Plus command and is not used in PL/SQL. So your code should look like this:
set serveroutput on
var rc refcursor;
declare
mycount number(19);
begin
sprocvPOP_GetvemployeeByFilter (NULL,NULL,1,10,mycount,:rc);
dbms_output.put_line(mycount);
end;
/
print rc;
However, it turns out you are using SQL Developer not SQL*Plus client to run your code. Not many SQL*Plus commands are natively supported in SQL Developer. The list is here.
The latest versions of the tool come with a Command Line interface which is very neat. Find out more.
Alternatively, use the built-in Run PL/SQL functionality as described in this tutorial

SQLPLUS Command Skipped: set serveroutput on;

In ORACLE SQL Developer, this gets execute when am trying to run procedure call with its output.
create or replace
procedure allparam_proc(name varchar2,nestedtable_param VARCHAR2_TT)
is
begin
DBMS_OUTPUT.PUT_LINE('allparam_proc');
FOR i IN nestedtable_param.FIRST..nestedtable_param.LAST LOOP
DBMS_OUTPUT.PUT_LINE(nestedtable_param(i));
END LOOP;
end;
Problem :
set serveroutput on;
declare
fruits VARCHAR2_TT := VARCHAR2_TT('Orange','Kumquat','Grape','Banana');
begin
allparam_proc('leo',fruits);
end;
Output :
line 1: SQLPLUS Command Skipped: set serveroutput on;
In SQL Developer, Enabling serveroutput can be done via View -> Dbms Output
Using Semicolon is fine. But, Select what ever requires to be executed, and F5 (Execute as a Script) would be enough.
Good Practice, is to end every PL/SQL block with a / though the tool do it implicitly sometimes. Atleast it improves readability and continuity when the IDE has multiple anonymous PL/SQL blocks. Answers here have great explanations in detail.

How do I exit a script in SQLPlus when an error occurs and return to the SQLPlus prompt, without disconnecting or exiting SQLPlus?

I have some scripts that get run often, always from within a connected SQLPlus session.
I need a way to exit the script when an error occurs, without disconnecting or exiting SQLPlus itself. 100% of the time, when an error occurs, the connected DBA will need to issue one or more commands into the session. 100% of the time, when an error occurs, there are other SQLPlus statements (and thus must be outside of a BEGIN..END;) later on in the script that must not be executed or serious problems could arise.
NOTE: If you suggest WHENEVER SQLERROR EXIT then you didn't read the above text. That will disconnect and exit SQLPlus in addition to the script, which is not acceptable behavior.
I've found an interesting idea here which, when combined with spencer7593's answer, will get me selective sub-script calling, to which I can pass the PL/SQL output values. To wit:
VAR continue number;
EXEC :continue := 1;
BEGIN
SELECT some_bool_test() INTO :continue FROM dual;
END;
SET termout OFF
COLUMN script_name NEW_VALUE v_script_name
SELECT decode(:continue, 1, 'run_stuff.sql', 'skip.sql') script_name FROM dual;
SET termout ON
#&v_script_name :some_other_values
Where skip.sql is an empty text file.
UPDATE: I've moved most of this into a RUN.SQL file, where I pass in the boolean (0 or 1) as &1, the script name to call on success as &2, and then any other expected parameters to pass to the called script. Thus, it ends up looking something like this:
VAR continue number;
EXEC :continue := 1;
BEGIN
SELECT some_bool_test() INTO :continue FROM dual;
END;
#run.sql :continue 'run_stuff.sql' :some_other_values
It's not possible.
SQLPlus doesn't provide that level of control over the execution of a script.
Obviously, you'd need to AVOID using the WHENEVER SQLERROR EXIT ... command.
It's possible to gain conditional control over which SQL statements do or do not get executed as a result of raised exceptions (errors) using PL/SQL. But that doesn't address SQLPlus commands (which cannot be executed from within a PL/SQL block.)
DECLARE
lb_continue BOOLEAN;
BEGIN
lb_continue := TRUE;
BEGIN
sql statement
EXCEPTION
WHEN OTHERS THEN
lb_continue = FALSE;
END;
IF lb_continue THEN
BEGIN
sql statements
EXCEPTION
WHEN OTHERS THEN
lb_continue := FALSE;
END;
END;
Of course, that approach has it's own limitations and issues. Any DDL statements would need to be called dynamically; the easiest way to do that is an EXECUTE IMMEDIATE statement.
The biggest issue (in your case) is that it's not possible to execute SQLPlus commands from inside a PL/SQL block.
You can't exit the script and stay in SQL*Plus, but you can stop executing things. It isn't pretty, but assuming you can modify the script to add the control flow then you can just about do this with bind variable.
set serveroutput on
var flag char;
exec :flag := 'Y';
begin
if :flag != 'Y' then
raise program_error;
end if;
dbms_output.put_line('Doing some work');
/* Check for some error condition */
if 0 != 1 then
raise program_error;
end if;
/* Only reach this if earlier statements didn't fail
* but could wrap in another flag check if needed */
dbms_output.put_line('Doing some more work');
exception
when program_error then
dbms_output.put_line(sqlerrm);
:flag := 'N';
when others then
/* Real exception handling, obviously */
dbms_output.put_line(sqlerrm);
:flag := 'N';
end;
/
-- DML only does anything if flag stayed Y
select sysdate from dual
where :flag = 'Y';
-- Optional status message at the end of the script, for DBA info
set feedback off
set head off
select 'Something went wrong' from dual where :flag != 'Y';
set feedback on
set head on
When executed:
SQL> #script
PL/SQL procedure successfully completed.
Doing some work
ORA-06501: PL/SQL: program error
PL/SQL procedure successfully completed.
no rows selected
Something went wrong
SQL>
Any PL/SQL blocks in the script can check the flag status at the start, and raise program_error (just as a handy pre-defined exception) to jump back out. Anything that errors inside a PL/SQL block can update the bind variable flag, either directly or in an exception handler. And any non-PL/SQL DML can have an additional where clause to check the flag status, so if it's been set to N by the time that statement is reached, no work is done. (For an insert I guess that would mean not using the values form).
What this can't do is deal with any errors from plain SQL statements, but I'm not sure if that's an issue. If it is then those might need to be changed to dynamic SQL inside a PL/SQL block.
I know its old, but these two instructions at the very begining of the SQL script do the work:
WHENEVER SQLERROR EXIT FAILURE ROLLBACK
WHENEVER OSERROR EXIT FAILURE ROLLBACK

call a oracle procedure from inside a sql block

If I have a .sql file with this :
begin
exec dbms_stats.gather_table_stats('schema',table');
end;
/
Should I need to use :
call 'exec dbms_stats.gather_table_stats('schema',table')';
I cannot test it out because of system problems so i am posting my query here.
As far as I can tell, both are flawed - exec is used in SQL/Plus without a begin/end block, and call is definitely not PL/SQL; you'd also probably have to escape the single quotes inside your call statement.
You can just use
begin
dbms_stats.gather_table_stats('ALERTS_OWNER','ASYNC_PROCESSING_REQUEST_T');
end;

Oracle refresh materialized view - Compile error

Im trying to execute a refresh on a materialized view, but I cant get the script to compile.
CREATE OR REPLACE PROCEDURE REFRESH_MV AS
BEGIN
exec DBMS_MVIEW.REFRESH('my_mat_view_mv','C');
END REFRESH_MV;
I get the message:
ORA-06550: line 3, column 9:
PLS-00103: Encountered the symbol
"DBMS_MVIEW" when expecting one of the
following:
:= . ( # % ; immediate The symbol
":=" was substituted for "DBMS_MVIEW"
to continue.
Am i doing something wrong ? Need to import anything?
Update
CREATE OR REPLACE PROCEDURE REFRESH_MV AS
BEGIN
EXECUTE DBMS_MVIEW.REFRESH('my_mat_view_mv','C');
END REFRESH_MV;
(S1917) Expecting: ( ; #
IMMEDIATE
CREATE OR REPLACE PROCEDURE REFRESH_MV AS
BEGIN
EXECUTE IMMEDIATE DBMS_MVIEW.REFRESH('my_mat_view_mv','C');
END REFRESH_MV;
Warning: compiled but with compilation errors
This is an Oracle 10g XE, hope thats no problem.
Thanks in advance !
I think if you just eliminate the "exec" altogether it might work better. "exec" is a SQL*Plus command. IOW, try:
CREATE OR REPLACE PROCEDURE REFRESH_MV AS
BEGIN
DBMS_MVIEW.REFRESH('my_mat_view_mv','C');
END REFRESH_MV;

Resources