Trigger success with compilation error oracle - oracle

I have these tables
PUBRED (cod_pub, title, year, type, medium)
AUTHOR (login, name, surname, institution, country)
AUTHOR_ONE (login, cod_pub)
PUB_CITA (cod_pub, cod_pub_cited)
And I have to get that citations to a publication should always be after it
I have the following trigger but it gives me compilation errors and I don't find any errors looking in other questions
Create or replace trigger works_trg_02
Before insert or update on pub_cita
For each row
Declare
Cnt number;
Begin
Select count (*) into cnt
from pubred pr
inner join pub_cita pc
on :new.pc.cod_pub = pr.cod_pub
inner join pubred pr2
on :new.pc.cod_pub_cited = pr2.cod_pub
where pr.year < pr2.year then 1
Else 0 end = 0;
If cnt <> 0 then
Raise_application_error ('-20001', 'Not possible');
End if;
End works_trg_02;
/
I get the typical error from 'ORA-24344: success with compilation error'
And when doing the inserts to prove it I get 'ORA-04098: trigger 'FIDDLE_WIXYFBGEUZDXILZQBEGR.WORKS_TRG_02' is invalid and failed re-validation'
I have searched other similar questions that have been asked around here adapting my initial solution and I have not been successful and I believe that everything there is is correct.

First, when you get ORA-24344: success with compilation error, you should run show errors, or query the user_errors or all_errors views to find your actual error message.
Second, this is wrong: :new.pc.cod_pub. The :new variable is a record, the row of the table (pub_cita) currently being inserted. You can just say :new.cod_pub.
Third, a trigger can't query its own table - so you can't have pub_cita in your SELECT query. Which is fine, you can refer to it using :new.
Fourth, what is this?
where pr.year < pr2.year then 1
Else 0 end = 0;
I think you started a CASE statement, then deleted part of it? It's not valid syntax.
See if this works for you:
Create or replace trigger works_trg_02
Before insert or update on pub_cita
For each row
Declare
Cnt number;
Begin
Select count (*) into cnt
from pubred pr
inner join pubred pr2
on :new.cod_pub_cited = pr2.cod_pub
where pr.year < pr2.year
and pr.cod_pub = :new.cod_pub
;
If cnt <> 0 then
Raise_application_error ('-20001', 'Not possible');
End if;
End works_trg_02;
/

Related

Trigger do not compile

I have a database that is made like this
works_on(ssn,project_number,hours)
and i have a trigger that asks me
that if an emp works more than 50 hours on a project it cannot be put on a 2 project.
if an emp works more than 70 hours on 2 projects it cannot be associated on a 3 project
an emp can only be associated to a max of 6 project
Sorry for my attempt i'm just learning how to make triggers. I have an error near the select statement:
Errore(8,6): PLS-00103: Encountered the symbol "SELECT" when expecting
one of the following: ( - + case mod new not null
continue
avg count current exists max min prior sql stddev sum variance
execute forall merge time timestamp interval date pipe <an alternat
My trigger so far:
create or replace trigger exe
before insert on worsk_on
for each row
declare
too_much_hours EXCEPTION;
no_hours_left EXCEPTION;
too_projects EXCEPTION;
begin
if hours>100
then raise too_much_hours;
end if;
elsif (select count(project_number),ssn,sum(hours) from worsk_on
where count(project_number) > 1 and (sum(hours)>100)
group by ssn,project_number)
then raise no_hours_left;
end if;
else count( porject_number)>6
then raise too_projects;
end if;
EXCEPTION
when too_much_hours then raise_application_error(-20000,'ore progetto sature');
when no_hours_left then raise_application_error(-19000,'ore progetti sature');
when too_projects then raise_application_error(-15151,'ore progetti sature');
There are many errors:
You have not declared a PL/SQL hours variable.
You are using SELECT inside an IF statement.
The SELECT statement does not have an INTO clause.
You are selecting all the ssn and project_number and do not have a filter to correlate it to the row being inserted.
You have spelling mistakes in worsk_on and porject_number.
The third COUNT( project_number ) is not valid as you are not in a SELECT statement.
You have elsif and else statements with no corresponding IF statement (as you have closed the previous statements with END IF.
There may be more (for example, if you fix all of them then I expect you'll get a mutating table exception as you are aggregating over the table you are inserting into.)

Executing the PL/SQL block gives an error which is not understandable

The question given was to write a PL/SQL block to print the details of the customers whose total order quantity is greater than 200 where the Customer table had ID number(5) primary key, Name varchar2(20), Contact_No varchar2(10) and the Order table had Order_Id number(5) primary Key, Quantity number(4) not null, C_id number(5) references Customer(ID).
If no record is found "No Records Found" is to be printed out.
This is the Code I wrote:
SET SERVEROUTPUT ON;
begin
dbms_output.put_line('Customer_Id ' || 'Customer_Name '|| 'Customer_Phone');
for cur_d in (select o.C_ID,total AS sum(o.QUANTITY) from Orders o group by o.C_ID) loop
from Customers c
where c.ID = cur_d.C_ID and cur_d.total > 200;
dbms_output.put_line(c.ID || c.Name || c.Contact_No);
end loop;
end;
/
The error I faced was -
for cur_d in (select o.C_ID,total AS sum(o.QUANTITY) from Orders o group by o.C_ID) loop
ERROR at line 2:
ORA-06550: line 2, column 41:
PL/SQL: ORA-00923: FROM keyword not found where expected
ORA-06550: line 2, column 15:
PL/SQL: SQL Statement ignored
ORA-06550: line 3, column 1:
PLS-00103: Encountered the symbol "FROM" when expecting one of the following:
( begin case declare exit for goto if loop mod null pragma
raise return select update while with '<'an identifier'>'
'<'a double-quoted delimited-identifier'> ')
Even after you correct the substantial that have been pointed out your procedure will still fail. You indicate that if no record is found printing a message to that effect. That in itself is ambiguous. Does that mean for the no records in the data table or no records for a given customer? Either way you have no code to produce such a message. How do you expect it to be written. Finally, SQL is set based processing so you need to start thinking in terms of sets instead of loops. The following reduces the db access to a single query; the loop is only to print results.
begin
dbms_output.put_line('Customer_Id ' || 'Customer_Name '|| 'Customer_Phone' || 'Total Orders');
for cur_d in (
with order_totals as
( select c_id, sum (quantity) order_total
from orders
group by c_id
having sum(quantity) > 200
)
select c.id, c.name, c.contact_no
, case when o.c_id is null
then 'No Records Found'
else to_char(o.order_total)
end order_total
from customers c
left join order_totals o
on c.id = o.c_id
order by c.id
)
loop
dbms_output.put_line(cur_d.ID || cur_d.Name || cur_d.Contact_No || cur_d.order_total);
end loop;
end;
The results are jammed together just as you initially had them. You need to workout their presentation.
There is a "select into" part missing between "for .. loop" and "from" parts. It has to be like this in order to work
for ..... loop
select some_column -- <-- this line is missing
into some_variable -- <-- this line is missing too
from ..........
This is the kind of issue where formatting your code will make the problem obvious. If you always start a new line and indent after for xxx in ( and also place the closing bracket on its own line, and include some gaps between commands, you'll get this, which is clearly wrong:
begin
dbms_output.put_line('Customer_Id ' || 'Customer_Name '|| 'Customer_Phone');
for cur_d in (
select o.c_id, total as sum(o.quantity)
from orders o
group by o.c_id
)
loop
from customers c
where c.id = cur_d.c_id
and cur_d.total > 200;
dbms_output.put_line(c.id || c.name || c.contact_no);
end loop;
end;
The first statement inside the loop seems to be missing something, as ekochergin mentioned.
total as sum(o.quantity) is backwards as Turo mentioned.
If you want id, name and contact_no to be printed in columns, you should look at lpad and rpad for formatting them. Just concatenating them together will produce something unreadable.
The dbms_output inside the loop refers to c.id, c.name and c.contact_no, but the record is called cur_d, not c.
Also cur_d is a slightly confusing name for a record (it's not a cursor). I always use r for cursor records unless there is some other r involved that it could be confused with.

PL SQL Function -compilation errors

I'm new to pl sql ,been trying to execute this function but getting compilation errors.
create or replace function "rural_finance" return number is
total number(13) :=0;
begin
select
(select "RURAL FINANCE " from rural_master_view1 t where load_date='apr-15' and activity='FINANCE_AMOUNT')
-
(select "RURAL FINANCE " from rural_master_view1 t where load_date='may-15' and activity='FINANCE_AMOUNT')
-
(select sum(disb_amount)
from retail_disbursal
where load_date = 'may-15'
and subproduct_name = 'TRACTOR') into total from dual
return total ;
end rural_finance;
Unfortunately, my pl-sql developer somehow is not displaying those errors ,so i'm not able to figure out the issue.
Also,when trying to recompile it ,it says 'object does not exist' or already deleted.
Thanks.
First:
If You use table alias (here: "t") then:
from rural_master_view1 t where t.load_date='apr-15' and t.activity='FINANCE_AMOUNT
and as was said - ";" after dual:
into total from dual**;**

ORA-01422: exact fetch returns more than requested number of rows pl/sql

I have this proc in my PL/SQL.
when i run it in sql dev, it is giving me exactly one row (one column)
PROCEDURE Newpo_code(sp_code OUT VARCHAR2)
IS
BEGIN
SELECT To_char(Max(num))
INTO sp_code
FROM (SELECT "ordernumber" num
FROM "purchaseorder"
WHERE ROWNUM = 1
ORDER BY "pkpurchaseorderid" DESC)
WHERE ROWNUM = 1;
SELECT Substr(sp_code, 10, 2)
INTO sp_code
FROM "purchaseorder";
END newpo_code;
but when i run it from code level
it is giving me exception
ORA-01422: exact fetch returns more than requested number of rows
What am I missing here?
I searched this exception but found no helpful results.
There is not much to go on, but most likely this is the line failing:
select substr(SP_CODE,10,2) into SP_CODE from "PurchaseOrder";
Why? Because there are probably more than 1 row in the PurchaseOrder table, which field you are trying to fit in one variable, SP_CODE.
You probably need a where clause on PurchaseOrder.
PROCEDURE Newpo_code(sp_code OUT VARCHAR2)
IS
BEGIN
SELECT To_char(Max(num))
INTO sp_code
FROM (SELECT "ordernumber" num
FROM "purchaseorder"
WHERE ROWNUM = 1
ORDER BY "pkpurchaseorderid" DESC)
WHERE ROWNUM = 1;
SELECT Substr(sp_code, 10, 2)
INTO sp_code
FROM dual;
END newpo_code;
Done!
Thanks anyways.

Why I'm getting the ORA-01003: no statement parsed error?

Why am I getting this error and what does it mean by no statement parsed.
ORA-01003: no statement parsed
Here is the code:
PROCEDURE ORIGINAL_TABLE.UPDATE_GROUPS IS
-- cursor loaded with the swam groups
CURSOR cursor1 IS
SELECT ID, NEW_DESCRIPTION
FROM NEW_TABLE.NEW_GROUP_TABLE#DB_LINK.X;
BEGIN
FOR C1_REC IN cursor1 LOOP
UPDATE
ORIGINAL_TABLE."GROUPS"
SET
GROUP_ID = C1_REC.ID
WHERE
ORIGINAL_TABLE."GROUPS".DESCRIPTION = C1_REC.NEW_DESCRIPTION;
IF (SQL%ROWCOUNT = 0) THEN
INSERT INTO
ORIGINAL_TABLE.GROUPS("GROUP_ID", "DESCRIPTION")
VALUES (C1_REC.ID, C1_REC.NEW_DESCRIPTION);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END;
What I try to do with the code above is to update and old table with the values from a new table and in case that the new group doesn't exist insert it.
Update: Changed %ROWCOUNT > 0 for %ROWCOUNT = 0
Use MERGE statement, it does update/insert stuff more efficiently and pay attention your plsql doesn't provide it is intended for. It tries to make an update statement and if a record found it inserts another record. In order to fix it use
IF (SQL%ROWCOUNT = 0)
I presume the reason of the issue is the . in DBLINK name.
Moreover I would suggest to get rid of quotes for tables/fields just in case as well as schema name.
Another words delete all ORIGINAL_TABLE.
merge into groups g
using (
SELECT ID, NEW_DESCRIPTION
FROM NEW_TABLE.NEW_GROUP_TABLE#DB_LINK.X
) nt
on (nt.NEW_DESCRIPTION = g.description )
when matched then update set g.group_id = nt.id
when non matched then insert(GROUP_ID, DESCRIPTION)
values(nt.id, nt.NEW_DESCRIPTION)

Resources