SQL Trigger with cursor not working - sql

I'm doing a sql work but I'm getting trouble with creating a trigger and I have no idea why.
Here's the code:
CREATE OR REPLACE TRIGGER artigo_funcionario
BEFORE INSERT ON encomendaartigo
FOR EACH ROW
DECLARE
artigo_invalido exception;
artigo number(3);
auxiliar number(1):=0;
auxiliar_numero number(3);
CURSOR dotacao_funcionario is
select a.artigo_id
from artigo a, familia fa, dotacao d, encomenda e, funcionario f, categoria c
where e.encomenda_id = NEW.encomenda_id
and f.funcionario_id=e.funcionario_id
and f.categoria_id=c.categoria_id
and d.categoria_id=c.categoria_id
and fa.familia_id=d.familia_id
and a.familia_id=fa.familia_id;
BEGIN
open dotacao_funcionario;
loop
fetch dotacao_funcionario into artigo;
EXIT WHEN dotacao_funcionario%notfound;
auxiliar_numero := NEW.artigo_id;
if(artigo = auxiliar_numero) then
auxiliar:=1;
end if;
end loop;
close dotacao_funcionario;
if(auxiliar=0) then
raise artigo_invalido;
end if;
EXCEPTION
WHEN artigo_invalido THEN
dbms_output.put_line('O funcionário não pode encomendar o artigo introduzido');
END;
/
Be aware that the problem is not with the cursor so don't worry about the tables I'm using. the only one that is relevant is the "encomendaartigo" and it has the following attributes: "encomenda_id", "artigo_id".
The problem is that I'm can't quite use the "new.xxxxx" operator. if ran, the compiler log shows the following:
Error(8,7): PL/SQL: SQL Statement ignored
Error(10,30): PL/SQL: ORA-00904: "NEW"."ENCOMENDA_ID": identificador inválido
Error(25,7): PL/SQL: Statement ignored
Error(25,29): PLS-00201: identifier 'NEW.ARTIGO_ID' must be declared
I've tried everything and nothing seems to be working.

You are missing the colon before the NEW. e.g.)
auxiliar_numero := :NEW.artigo_id;
Not
auxiliar_numero := NEW.artigo_id;
Optional implementation per your comments:
CREATE OR REPLACE TRIGGER artigo_funcionario
BEFORE INSERT ON encomendaartigo
FOR EACH ROW
DECLARE
l_check_artigo_id number := 0;
CURSOR dotacao_funcionario is
select 1
from artigo a, familia fa, dotacao d, encomenda e, funcionario f, categoria c
where e.encomenda_id = :NEW.encomenda_id
and f.funcionario_id=e.funcionario_id
and f.categoria_id=c.categoria_id
and d.categoria_id=c.categoria_id
and fa.familia_id=d.familia_id
and a.familia_id=fa.familia_id
and a.artigo_id = :NEW.artigo_id;
BEGIN
open dotacao_funcionario;
fetch dotacao_funcionario into l_check_artigo_id;
IF l_check_artigo_id = 1 then
raise_application_error(-20001, 'O funcionário não pode encomendar o artigo introduzido');
END IF;
CLOSE dotacao_funcionario;
EXCEPTION
WHEN OTHERS THEN
IF sqlcode = -20001 then
dbms_output.put_line('O funcionário não pode encomendar o artigo introduzido');
END IF;
-- a simple RAISE will re-raise the exception
RAISE;
END;
/

Related

Error in return of PLSQL ORACLE Not Working

This Code is:
CREATE OR REPLACE
PROCEDURE Actualiza_Saldo(fecha_ini IN DATE, fecha_fin IN DATE) RETURN NUMBER
AS
fechaTemp DATE;
diasTotales NUMBER := fecha_fin- fecha_ini;diasLaborables NUMBER;
sab VARCHAR2(10) := 'SÁBADO';dom VARCHAR2(10) := 'DOMINGO';diasTemp VARCHAR2(10);
BEGIN
diasLaborables:= diastotales;
FOR i IN 0..diasTotales LOOP
fechaTemp := fecha_ini + i;
DBMS_OUTPUT.PUT_LINE(to_char(fechaTemp));
diasTemp := TO_CHAR(fechaTemp, 'DAY', 'NLS_DATE_LANGUAGE=SPANISH');
IF (TRIM(diasTemp)=sab or TRIM(diasTemp)=dom) THEN
diaslaborables := diaslaborables-1;
END IF;
END LOOP;
dbms_output.put_line(diaslaborables);
RETURN diasLaborables;
END Actualiza_Saldo;
If I execute without returning it works, if I try to return a value it fails, I do not know what could be happening.
The error of oracle is:
Warning: la ejecución ha terminado con advertencias
PROCEDURE Actualiza_Saldo(fecha_ini Compilado.
Error que empieza en la línea 1 del comando:
EXEC Actualiza_Saldo();
Informe de error:
ORA-06550: línea 1, columna 7:
PLS-00905: el objeto HR.ACTUALIZA_SALDO no es válido
ORA-06550: línea 1, columna 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The code with constant value:
CREATE OR REPLACE
PROCEDURE Actualiza_Saldo(fecha_ini IN DATE DEFAULT '10/08/2018', fecha_fin IN DATE DEFAULT '30/08/2018')
AS
fechaTemp DATE;
diasTotales NUMBER := fecha_fin- fecha_ini;diasLaborables NUMBER;
sab VARCHAR2(10) := 'SÁBADO';dom VARCHAR2(10) := 'DOMINGO';diasTemp VARCHAR2(10);
BEGIN
diasLaborables:= diastotales;
FOR i IN 0..diasTotales LOOP
fechaTemp := fecha_ini + i;
DBMS_OUTPUT.PUT_LINE(to_char(fechaTemp));
diasTemp := TO_CHAR(fechaTemp, 'DAY', 'NLS_DATE_LANGUAGE=SPANISH');
IF (TRIM(diasTemp)=sab or TRIM(diasTemp)=dom) THEN
diaslaborables := diaslaborables-1;
END IF;
END LOOP;
dbms_output.put_line(diaslaborables);
END Actualiza_Saldo;
EXEC Actualiza_Saldo();
And the exit of the code without the returns and the test values ​​is a route from the start date and the final date subtracting the days Saturday and Sunday.
PROCEDURE Actualiza_Saldo(fecha_ini Compilado.
anonymous block completed
10/08/18
11/08/18
12/08/18
13/08/18
14/08/18
15/08/18
16/08/18
17/08/18
18/08/18
19/08/18
20/08/18
21/08/18
22/08/18
23/08/18
24/08/18
25/08/18
26/08/18
27/08/18
28/08/18
29/08/18
30/08/18
14
But if I try to return the value the algorithm dies.
I have no idea what I am doing wrong or where is the fault, if you could help me I would greatly appreciate it.
Procedures cannot return a value, in Oracle, You can have out-parameters which would be visible after the procedure runs.
But here is another option you can try, instead of writing code to generate dates between two, try to do it using a single select query and open a out cursor to have the values populated after the proc completes
An example as follows
create or replace procedure generate_dates(start_date in date, end_date in date, result_set out sys_refcursor)
as
begin
open result_set for
select trunc(start_date)+level as output_dates
from dual
connect by level<=trunc(end_date)-trunc(start_date);
end;
if you are using sqlplus to connect to your database
you would call the proc as follows
var x refcursor
begin
generate_dates(date '2018-01-01',date '2018-12-31',:x);
end;
print x;
My mistake was that I was not doing a function but a procedure solved.
CREATE OR REPLACE
FUNCTION HR.Actualiza_Saldo(fecha_ini IN DATE/* DEFAULT '10/08/2018'*/, fecha_fin IN DATE/* DEFAULT '30/08/2018'*/) RETURN NUMBER
AS

I'm trying to use a variable from a cursor in the select statement of another cursor in pl/sql

I need to run a query that finds me the first 20 vehicles that are as close to another vehicle with specific terms. I'm writing this in SQL Developer on an oracle database.
Here's what I have so far:
DECLARE
TYPE cur_type IS REF CURSOR;
CURSOR lost_vehicles_cur IS
select
v.vin,
V.VEHICLE_ID
from d_vehicles V
where v.system_id =4 ;
make_cur cur_type;
l_cur_string VARCHAR2(2000);
l_make <type>;
l_model <type>;
l_vin <type>;
BEGIN
FOR vehicle IN lost_vehicles_cur LOOP
dbms_output.put_line('lost vehicle is '|| vehicle.vehicle_id);
l_cur_string := 'SELECT make_name, model_name,vin FROM vehicles where make=(select make from vehicles where vehicle_id= '
|| vehicle.vehicle_id || 'and rownum<=20 and system_id=3 and vehicle_status_id in (13,14) ';
OPEN make_cur FOR l_cur_string;
LOOP
FETCH make_cur INTO l_make, l_model, L_vin;
EXIT WHEN make_cur%NOTFOUND;
dbms_output.put_line('Related vehicles are ' || l_make || l_model || L_vin);
END LOOP;
CLOSE make_cur;
END LOOP;
END;
I used a previous answer to get to this however I get the following error when I run this:
ORA-06550: line 32, column 13: PLS-00103: Encountered the symbol "<" when expecting one of the following: constant exception table long double ref char time timestamp interval date binary national character nchar 06550. 00000 - "line %s, column %s:\n%s" *Cause: Usually a PL/SQL compilation error. –
You have to use parametrized cursor or dbms_sql:
DECLARE
TYPE cur_type IS REF CURSOR;
CURSOR lost_vehicles_cur IS
select
v.vin,
V.VEHICLE_ID
from d_vehicles V
where v.system_id =4 ;
cursor l_cur (ip_id in d_vehicles.VEHICLE_ID%type)
SELECT make_name, model_name,vin
FROM vehicles
where make in (select make
from vehicles
where vehicle_id= ip_id
and rownum<=20
and system_id=3
and vehicle_status_id in (13,14));
make_cur cur_type;
l_cur_string VARCHAR2(2000);
l_make <type>;
l_model <type>;
l_vin <type>;
BEGIN
FOR vehicle IN lost_vehicles_cur LOOP
dbms_output.put_line('lost vehicle is '|| vehicle.vehicle_id);
OPEN make_cur FOR l_cur (vehicle.vehicle_id);
LOOP
FETCH make_cur INTO l_make, l_model, L_vin;
EXIT WHEN make_cur%NOTFOUND;
dbms_output.put_line('Related vehicles are ' || l_make || l_model || L_vin);
END LOOP;
CLOSE make_cur;
END LOOP;
END;

ORA-21700: object does not exist or is marked for delete

I have package with Period and TableOfPeriod types:
TYPE Period
IS RECORD
( StartPeriod Date,
EndPeriod Date
);
TYPE TableOfPeriod
IS TABLE OF Period;
and in this package I have three simple function:
FUNCTION Temp1
RETURN TableOfPeriod IS
returnedValue TableOfPeriod := TableOfPeriod();
BEGIN
returnedValue.extend(1);
returnedValue(1).StartPeriod := sysdate-100;
returnedValue(1).EndPeriod := sysdate;
RETURN returnedValue;
END Temp1;
FUNCTION CalculateFine
return VARCHAR2
IS
freewillLockTableRP TableOfPeriod:=TableOfPeriod();
compulsoryLockTableRP TableOfPeriod:=TableOfPeriod();
BEGIN
--for testing
compulsoryLockTableRP:=Temp1();
FOR i IN compulsoryLockTableRP.FIRST..compulsoryLockTableRP.LAST LOOP
IF(((compulsoryLockTableRP(i).EndPeriod - compulsoryLockTableRP(i).StartPeriod)>1)) THEN
BEGIN
-- RAISE_APPLICATION_ERROR(-20001, 'Hello world');
SELECT T111.StartPeriod StartPeriod,
T111.EndPeriod EndPeriod
bulk collect into freewillLockTableFull
FROM TABLE(DistributeDaysByPeriods(compulsoryLockTableRP, 5)) T111;
END;
END IF;
END LOOP;
/*SELECT T111.StartPeriod StartPeriod,
T111.EndPeriod EndPeriod
-- BULK COLLECT INTO compulsoryLockTableRP
bulk collect into freewillLockTableFull
FROM TABLE(DistributeDaysByPeriods(compulsoryLockTableRP, 5)) T111;*/
--===========
--SOME OTHER PROCESSING
RETURN 'Ok '
|| '#r';
EXCEPTION
WHEN No_Data_Found THEN return 'No data found#g';
-- WHEN OTHERS THEN RETURN SQLERRM;
END CalculateFine;
When I execute this function, I have next error:
"ORA-21700: object does not exist or is marked for delete ORA-06512:
at "MyPackageName", line 1181 ORA-06512: at line 1
21700. 00000 - "object does not exist or is marked for delete""
where 1181 line is a line with Select statement of CalculateFine function. Can anybody tell me, whats wrong and how I can solve this problem?
Check if you have in the same folder where your package is located a file with the same name but with an extention *.~sql (e.g.: your_file_name.~sql). I had the same error but after I have deleted an *.~sql file I could compile my package without ORA errors.

A frustrating PL/SQL Error...PLS-00103

I have been learning PL/SQL for one of my classes and I am having a difficult time debugging the PLS-00103 error. I have searched the error online, but the solutions I have found aren't necessarily specific enough to solve my problem. Maybe I just need a few more eyes on this. Below you will find my code and the corresponding error message. Thank you in advance! The sample output is below the error.
Code:
create or replace procedure pro_AvgGrade as
min_avg NUMBER := 100;
max_avg NUMBER := 0;
bins NUMBER := 0;
binlen NUMBER := 10;
temp NUMBER := 0;
binprint NUMBER := 0;
CURSOR grades IS SELECT AvgGrade FROM (SELECT DeptName, AVG(GradeAsPercentage) AS AvgGrade FROM Department JOIN Course on Department.DeptId = Course.DeptId JOIN Offering on Course.CourseId = Offering.CourseId JOIN Registration on Offering.OfferingId = Registration.OfferingId GROUP BY DeptName ORDER BY DeptName ASC);
grade_tuple grades%ROWTYPE;
BEGIN
open grades;
for grade_tuple in grades loop
temp := grade_tuple.AvgGrade;
if (temp>max) then
max_avg := temp;
elsif (temp<min) then
min_avg := temp;
end if;
end loop;
close grades;
binprint := min_avg;
bins := max_avg-min_avg;
bins := bins/binlen;
dbms_output.put_line('DeptName AvgGrade: ');
LOOP
dbms_output.put('>' || min_avg || ',' || '<=');
min_avg := binlen+10;
dbms_output.put(min_avg);
dbms_output.put(' ');
i := i+1;
EXIT WHEN i>bins;
END LOOP;
END pro_AvgGrade;
/
begin
pro_AvgGrade;
end;
/
Error:
LINE/COL ERROR
-------- -----------------------------------------------------------------
19/15 PLS-00103: Encountered the symbol ")" when expecting one of the
following:
(
21/18 PLS-00103: Encountered the symbol ")" when expecting one of the
following:
(
Sample Output:
DEPTNAME AVGGRADE: >70, <=80 >80,<=90
May be it's because max and min are reserved words...so it looking for max() and min()...
But it looks more that you just made a mistake. I think you need to try this :
if (temp>max_avg) then
max_avg := temp;
elsif (temp<min_avg) then
min_avg := temp;
end if;
There is no need for parenthesis in your if block. Write it like this:
if temp>max then
max_avg := temp;
elsif temp<min then
min_avg := temp;
end if;

In Exception Log want to print data value

declare
v number;
c varchar2(20);
begin
select c into v from dual;
exception
when others
then
raise;
end;
while running this block i am getting exception because i m providing input on c dynamically (suppose) as character. i want raise will print the error with value of C.
Is there any way that we can add message + value of C in raise statement.
By adding simple :
Select CONCAT(raise,'C');
will print its value in the console