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.
Related
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;
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
I have a oracle procedure proc1 which adds two values and gives the result.I have to call this procedure from shell and show its result back to the shell.I am able to call that procedure from the shell,but it just shows that PL/SQL procedure successfully completed.But the result is not coming to the shell .
i am doing this to call the procedure from shell...
$ echo "execute proc1(10,10);"|sqlplus -s system/xxxxx#orcl
This is the procedure which is running fine .
create or replace procedure proc1
(N1 in number,N2 in number) is
begin
dbms_output.put_line(N1+N2);
end;
/
I need the output in the shell .Anyone plese help.
I am aware there is another answer showing how to use set serveroutput on and the procedure call on separate lines, however I am writing this answer as a one-liner to do the same thing.
Bascially you need to shove this into sqlplus:
set serveroutput on
execute proc1(10,10);
You might at first think this can be done on one line, separated with a semi-colon.
set serveroutput on; execute proc1(10,10);
However that doesn't work - you really need a newline character.
So the trick is to also use -e flag with echo, which can give you a newline with \n.
Using head -1 trims everyting but the line containing the procedure result.
Final one-line answer:
echo -e "set serveroutput on\n execute proc1(10,10);"|sqlplus -s system/xxxxx#orcl| head -1
P.S. I editted your question to remove the password :)
This may be a stupid idea. I am trying to write a SQL*Plus .sql script that I can call from a Windows batch file that itself generates a new .sql script using dbms_output.put_line. This is what I have so far for my script:
set echo off;
set serverout on;
conn user#pass;
spool E:\new_script.sql
DECLARE
CURSOR c_groups IS
SELECT * FROM table;
s varchar2(4000);
BEGIN
dbms_output.put_line('BEGIN');
FOR x IN c_groups LOOP
s := 'INSERT INTO TABLE blah VALUES ('''||x.name||''','||x.id||');';
END LOOP;
dbms_output.put_line(s);
dbms_output.put_line('COMMIT;');
dbms_output.put_line('END;');
dbms_output.put_line('/');
END;
/
spool off;
exit;
However, when I do this, my new_script.sql just says "PL/SQL procedure successfully completed." Any ideas how to make the dbms_out.put_line actually display their message?
And I'm not actually doing this to build insert statements - those are just a simple sample showing the gist of what I'm trying to do.
You have to connect first and then use SET command. So your three commands should be in
this order:
conn user#pass;
set echo off;
set serverout on;
Otherwise, serveroutput parameter will be set to its default
value, which is OFF and that the reason why dbms_output.put_line()
hasn't been working as expected.
You should execute dbms_output.put_line(s) inside the FOR loop:
FOR x IN c_groups LOOP
s := 'INSERT INTO TABLE blah VALUES ('''||x.name||''','||x.id||');';
dbms_output.put_line(s);
END LOOP;
Moreover it's redundant to spool BEGIN .. END block. The DML statements
(bunch of INSERT INTO statements in this case) terminated by semicolon will be
executed just fine without being included in the BEGIN END block.
As you run your script using *.bat file, It probably will be useful to use the
following commands:
set feedback off; -- To not spool messages like
-- PL/SQL procedure successfully completed
set termout off; -- to suppress the output from a command line.
Your approach could probably be boiled down to a simple SELECT statement:
conn user#pass;
set echo off;
set serverout on;
set feedback off;
set termout off;
set heading off;
spool E:\new_script.sql
SELECT 'INSERT INTO TABLE blah VALUES ('''||name||'''','||to_char(id)||');'
FROM table;
spool off;
exit;
SPOOL sends the results to a file; but it doesn't ensure that results are printed. To enable the printing to stdout; use the SERVEROUTPUT command.
set serveroutput on
This is generally a poor way of going about things; I recognise that you said this wasn't what you're actually doing but SQL is a set based language. Do things in bulk if at all possible.
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