Calling a stored procedure in a trigger in SQL DEVELOPER - oracle

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;

Related

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;

Can I execute procedure after select?

I am trying to make a script, which will verify my stored procedure's function. However, once I put execute store procedure there, I get this kind of error: PLS-00103: Encountered the symbol "NEW_PRODUCT" when expecting one of the following:
:= . ( # % ; immediate
The symbol ":=" was substituted for "NEW_PRODUCT" to continue.
My script looks like this:
DECLARE
id_unit number;
id_unit_old number;
var_materialid number;
var_processid number;
serial_no varchar(30);
product_name_new varchar(30);
BEGIN
SELECT max(id) INTO id_unit_old
FROM Unit;
execute new_product('NTB', 'Diablo', 'CPU-I7', 'GPU-M800', 'RAM-K2');
SELECT max(id) INTO id_unit
FROM Unit;
IF id_unit > id_unit_old THEN BEGIN
SELECT id_material, id_process, serial_number INTO var_materialid, var_processid, serial_no
FROM Unit
WHERE id = id_unit;
SELECT name INTO product_name_new
FROM Material
WHERE id = var_materialid;
ELSE
RAISE_APPLICATION_ERROR(-20002, 'Insert to table Unit has failed!');
END IF;
END;
Any suggestions what is the problem and how can I solve it? Thanks
Get rid of the execute word right before the new_product word, when you call a PL/SQL procedure from another procedure or from PL/SQL anonymous block you must call it by its name.

Outputting a single row in stored procedure (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>

PLSQL procedure execution error invalid statement

I'm following a tutorial on PL/SQL http://www.plsqltutorial.com/plsql-procedure/. I have created procedure with the following code on apex:
CREATE OR REPLACE PROCEDURE adjust_salary(
in_employee_id IN EMPLOYEES.EMPLOYEE_ID%TYPE,
in_percent IN NUMBER
) IS
BEGIN
UPDATE EMPLOYEES
SET salary = salary + salary * in_percent / 100
WHERE employee_id = in_employee_id;
END;
However when I try to run
exec adjust_salary(200,5);
I got error
ORA-00900: invalid SQL statement.
What is the problem and how to fix it?
I see nothing wrong with your PL/SQL. You should check to see if the Procedural Option is installed:
http://www.techonthenet.com/oracle/errors/ora00900.php

Dynamic SQL and out field in oracle procedure

I get error when I use this:
PROCEDURE GET_BY_CRIT(vchFilter varchar2(500),
intCantTotal OUT INT,
curResult OUT sys_refcursor)
IS
BEGIN
OPEN curResult FOR
'SELECT COLUMN1,COLUMN2 FROM SOME_TABLE WHERE '||vchFilter
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM SOME_TABLE WHERE '||vchFilter
INTO intCantTotal
END
Error:
ORA-00936: missed expression
But when I execute each sentence by separate it run correcly.
The error you're getting doesn't seem to make sense. Oracle should be throwing a compilation error because parameters to functions don't have a length. vchFilter should be declared as a VARCHAR2, not a VARCHAR2(500).
Additionally, as Lolo pointed out in the comments, statements in a PL/SQL block need to be terminated with semicolons.
PROCEDURE GET_BY_CRIT(vchFilter varchar2,
intCantTotal OUT integer,
curResult OUT sys_refcursor)
IS
BEGIN
OPEN curResult FOR
'SELECT COLUMN1,COLUMN2 FROM SOME_TABLE WHERE '||vchFilter;
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM SOME_TABLE WHERE '||vchFilter
INTO intCantTotal;
END;
Be aware as well that there is no guarantee that second SQL statement will see the same COUNT that the first SQL statement did unless you can guarantee that SOME_TABLE is not being modified by any other sessions at the same time you're querying it. I'd generally be rather wary of a need to run a query and execute a separate count-- that generally indicates a more basic problem. If you need the COUNT to be consistent with the query you're running, you'd want to add an analytic COUNT to your query and let the caller fetch that column.
PROCEDURE GET_BY_CRIT(vchFilter varchar2,
curResult OUT sys_refcursor)
IS
BEGIN
OPEN curResult FOR
'SELECT COLUMN1,COLUMN2, COUNT(*) OVER () cnt FROM SOME_TABLE WHERE '||vchFilter;
END;

Resources