Outputting a single row in stored procedure (oracle) - oracle

I'm trying to follow the example at http://dba-oracle.com/t_pl_sql_plsql_select_into_clause.htm
But when i however do
create or replace PROCEDURE age
is
declare
info movie%rowtype;
BEGIN
dbms_output.enable();
select * into info from movie where mo_id=1;
dbms_output.put_line('The name of the product is ' || info.mo_id);
END age;
/
It gives a couple of errors:
Error(4,1): PLS-00103: Encountered the symbol "DECLARE" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior external language The symbol "begin" was substituted for "DECLARE" to continue.
and
Error(14,8): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
what's wrong with it?

Try with the following, you do not need to have declare inside a procedure.
create or replace PROCEDURE
age
is
info movie%rowtype;
BEGIN
--dbms_output.enable();
select * into info from movie where mo_id=1;
dbms_output.put_line('The name of the product is ' || info.mo_id);
END age;
/
and to execute the procedure you could do
exec age

There are a couple of things in your code to take a look at:
First. As #Polppan has already mentioned, remove DECLARE keyword from your stored procedure. There is no need of it. You will need it however when you write anonymous PL/SQL block. Second. If you use dbms_output.enable() in your procedure then to display lines, I assume you are using sql*plus for this, you will need to invoke dbms_output.get_lines() otherwise it will not give you desired result. So to simplify that use set serveroutput on command of sql*plus to enable output. And do not mix dbms_output.enable() and setserveroutput on - use either of them. Not both. Here is an example:
SQL> CREATE OR REPLACE PROCEDURE Print_data
2 is
3 l_var_1 varchar2(101);
4 BEGIN
5 select 'Some data'
6 into l_var_1
7 from dual;
8 dbms_output.put_line(l_var_1);
9 END;
10 /
Procedure created
SQL> set serveroutput on;
SQL> exec print_data;
Some data
PL/SQL procedure successfully completed
SQL>

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.)

I am getting an error message in Oracle SQL stored procedure

I am trying the following code
CREATE OR REPLACE PROCEDURE sal2
AS
BEGIN
SELECT sal
FROM emp
END
And I'm getting this error
Error at line 7: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
( begin case declare end exception exit for goto if loop mod
null pragma raise return select update while with
<< continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall
merge pipe purge
5. from emp
6. return 1
7. END
What I want to do is to get a sal column from emp table.
There are multiple issues with code as following;
create or replace procedure sal2
AS
Lv_var number; -- added variable for holding select value
BEGIN
select sal
Into lv_var -- into is needed in select
from emp; -- you missed this semicolon
-- you must use where clause as into variable can hold single value
-- so you must restrict this query to return only 1 record.
END; -- you missed this semicolon
/
Cheers!!
First you have to put the semicolon at the end of each line and after the END keyword. Then the SELECT statement is also wrong you have to load the result in a variable.
Here is the solution for multiple rows.
CREATE OR REPLACE PROCEDURE sal2
AS
CURSOR c_salaries IS SELECT salary FROM employees;
TYPE t_salaries IS TABLE OF c_salaries%rowtype INDEX BY BINARY_INTEGER;
v_salaries t_salaries;
BEGIN
OPEN c_salaries;
FETCH c_salaries BULK COLLECT INTO v_salaries;
CLOSE c_salaries;
END;
And one for a single row result.
CREATE OR REPLACE PROCEDURE sal2
AS
v_salary employees.salary%rowtype;
BEGIN
SELECT salary INTO v_salary
FROM employees WHERE employee_id = 100;
END;

How to call stored procedure with only OUT parameter?

I have created a stored procedure in Oracle 11g:
CREATE OR REPLACE PROCEDURE greetings(cnt OUT VARCHAR2)
AS
BEGIN
SELECT COUNT(*)
INTO cnt
FROM SYS.all_tables;
END greetings;
but I am unable to call it.
I have tried the following code snippets:
EXEC GREETINGS();
EXEC GREETINGS;
CALL GREETINGS;
The procedure requires one parameter, so - provide it.
SQL> CREATE OR REPLACE PROCEDURE greetings(cnt OUT VARCHAR2)
2 AS
3 BEGIN
4 SELECT COUNT(*)
5 INTO cnt
6 FROM SYS.all_tables;
7 END greetings;
8 /
Procedure created.
One option, which works everywhere, is to use an anonymous PL/SQL block:
SQL> set serveroutput on
SQL> declare
2 l_cnt number;
3 begin
4 greetings(l_cnt);
5 dbms_output.put_line(l_cnt);
6 end;
7 /
87
PL/SQL procedure successfully completed.
Another one works in SQL*Plus (or any other tool which is capable of simulating it):
SQL> var l_cnt number;
SQL> exec greetings(:l_cnt);
PL/SQL procedure successfully completed.
SQL> print l_cnt;
L_CNT
----------
87
Regarding the call example, this is explained in EXECUTE recognizes a stored procedure, CALL does not. It's not obvious from the syntax documentation but it does require brackets, so it is (rather unhelpfully) rejecting the whole thing and giving the impression that greetings is the problem, when actually it is not:
SQL> call greetings;
call greetings
*
ERROR at line 1:
ORA-06576: not a valid function or procedure name
while using the mandatory brackets gets you the real issue:
SQL> call greetings();
call greetings()
*
ERROR at line 1:
ORA-06553: PLS-306: wrong number or types of arguments in call to 'GREETINGS'
As others have pointed out, you are missing the parameter.
SQL> var n number
SQL>
SQL> call greetings(:n);
Call completed.
SQL> print :n
N
----------
134
execute is just a handy SQL*Plus shortcut for the PL/SQL block begin xxx; end; which is less fussy about brackets and gives the same error message with or without them.
(variable and print are SQL*Plus commands and may not be supported in other environments.)
There's no problem with the procedure body. You can call like this :
SQL> var nmr number;
SQL> exec greetings(:nmr);
PL/SQL procedure successfully completed
nmr
------------------------------------------
306 -- > <a numeric value returns in string format>
Oracle doesn't care assigning a numeric value to a string. The execution prints the result directly, but whenever you want you can recall that value of variable(nmr) again, and print as
SQL> print nmr
nmr
---------
306

Calling a stored procedure in a trigger in SQL DEVELOPER

I'm trying to call the following stored procedure...
CREATE OR REPLACE PROCEDURE PRC_EXAMEN_SUELDO(fecha_hoy varchar2)
AS
BEGIN
IF fecha_hoy= 'WEDNESDAY' then
RAISE_APPLICATION_ERROR(-20777, 'Los ' || fecha_hoy ||' no se puede cambiar el sueldo');
END IF;
END;
...inside this trigger:
CREATE OR REPLACE TRIGGER TRG_EXAMEN_SUELDO
BEFORE UPDATE OF SALARY ON EMPLOYEES
FOR EACH ROW
DECLARE
HOY VARCHAR(50);
BEGIN
HOY:= TO_CHAR (SYSDATE, 'DAY');
execute PRC_EXAMEN_SUELDO (HOY);
END;
But it throws the following error:
LINE/COL ERROR
--------- -------------------------------------------------------------
5/13 PLS-00103: Encountered the symbol "PRC_EXAMEN_SUELDO" when expecting one of the following:
:= . ( # % ; immediate
The symbol ":=" was substituted for "PRC_EXAMEN_SUELDO" to continue.
Errors: check compiler log
I'm using the HR schema of Oracle.
The purpose of the procedure is to check if the day sent is equal to the day of sysdate. If it is, it activates the error.
Supposedly, after compiling this line of code:
set serveroutput on;
update employees set salary = salary + 100 where employee_id = 100;
The trigger should check if according to the sysdate, the change can be done. Else, it throws the specified error.
The stored procedure works properly, but the trigger doesn't. Any help would be appreciated.
EXECUTE is a SQL*Plus command (Docs) for executing stored procedures, ad hoc
set serveroutput on
exec hello -- hello is a procedure that simply dbms_output 'hello' back
Running this in SQL Developer as a script, or in an interactive shell like SQL*Plus or SQLcl, I get
hello
PL/SQL procedure successfully completed.
But these clients have a command interpreter that deals with 'exec' which is short for EXECUTE. It's not part of the PL/SQL language though.
In your trigger body, you'd simply do:
CREATE OR REPLACE TRIGGER TRG_EXAMEN_SUELDO
BEFORE UPDATE OF SALARY ON EMPLOYEES
FOR EACH ROW
DECLARE
HOY VARCHAR(50);
BEGIN
HOY:= TO_CHAR (SYSDATE, 'DAY');
PRC_EXAMEN_SUELDO (HOY);
END;

How to write an Oracle procedure with a select statement (Specifically on SQL Developer)?

I want to create a simple Oracle Stored procedure on SQL Developer that will return some records on a simple select query. I do not want to pass in any parameter, but I just want the Records to be returned back from the procedure into a result set -> a suitable variable.
I have been trying to use the following syntax :
create or replace PROCEDURE Getmarketdetails2(data OUT varchar2)
IS
BEGIN
SELECT *
into data
from dual;
END Getmarketdetails2;
But it gives me an error while I try to execute with the following exec statement -->
Declare a Varchar2;
exec Getmarketdetails2(a);
Error: PLS-00103: Encountered the symbol "end-of-file" when expecting "something else".
Cause: Usually a PL/SQL compilation error.
Appreciate if anyone can help me out of this long pending situation! I have tried enough to find a basic guide to create a simple Oracle stored procedure and execute it in SQL Developer, but none of them answer to the point!!
You want:
DECLARE
a VARCHAR2(4000); -- Give it a size
BEGIN -- Begin the anonymous PL/SQL block
Getmarketdetails2(a); -- Call the procedure
DBMS_OUTPUT.PUT_LINE( a ); -- Output the value
END; -- End the anonymous PL/SQL block
/ -- End the PL/SQL statement
or:
VARIABLE a VARCHAR2(4000); -- Create a bind variable
EXEC Getmarketdetails2(:a); -- Execute the procedure using the bind variable
PRINT a -- Print the bind variable
Assuming an up-to-date Oracle version, you can use dbms_sql.return_result()
create or replace PROCEDURE Getmarketdetails2
IS
c1 SYS_REFCURSOR;
BEGIN
OPEN c1 FOR
SELECT *
from dual;
DBMS_SQL.RETURN_RESULT(c1);
END Getmarketdetails2;
/
Then simply run
exec Getmarketdetails2
The only drawback is that SQL Developer only displays the result as text, not as a proper result grid.
This is how I return a cursor in Oracle
PROCEDURE GetAllData (P_CURSOR OUT SYS_REFCURSOR)
IS
BEGIN
OPEN P_CURSOR FOR
SELECT *
FROM TABLE ;
END GetAllData ;
Declare a Varchar2;
exec Getmarketdetails2(a);
Your procedure is ok;
Instead of above query, use below query to run sp:
Declare
a Varchar2(10);
Begin
Getmarketdetails2(a);
End;

Resources