SUM() of rows in Trigger(PL/SQL) - oracle

This is the table "Cars":
Cars(carId,color,price);
carId------color-------price
125 red 20000
101 blue 10000
104 black 30000
125 orange 15000
-and so on
I want to create a trigger, which will verify before insertion, if the sum of price is greater than
30000. And here is my code.
CREATE OR REPLACE TRIGGER CarSum
BEFORE INSERT OR UPDATE ON Cars FOR EACH ROW
DECLARE
v_sum Cars.price%TYPE;
BEGIN
SELECT SUM(price)
INTO v_sum
FROM Cars
WHERE :NEW.carId=Cars.carId;
if v_sum >30000 then
raise_application_error(-20000,'Very expensive');
end if;
END;
/
INSERT INTO Cars VALUES(125,"red",10000);
And I get this error: ORA-04098: trigger is invalid and failed re-validation
I tried to do it with views(create a virtual table of Cars,and use it in trigger instead of Cars), but it isn't working.

Related

Warning: Trigger created with compilation error

I have two tables, seat_allocation and programme_code. I want to create a trigger for checking if the number of entries into the seat_allocation are equal to the max_seats(column in programm_code table) for that prog_code(column in programme_code table). This is my code:
SQL> create or replace trigger seats_full
2 before insert on seat_allocation
3 for each row
4 declare
5 cnt programme_code.max_seats%type;
6 max programme_code.max_seats%type;
7 begin
8 select count(*) into cnt from seat_allocation where prog_code=(select prog_code from programme_code where prog_code = :NEW.prog_code);
9 select max_seats into max from programme_code where prog_code=(select prog_code from programme_code where prog_code = :NEW.prog_code);
10 if max=cnt then
11 RAISE_APPLICATION_ERROR(-21000,'No vacant seats available');
12 end if;
13 end;
14 /
It gives Warning:Trigger created with compilation error. Can you please help me figure out what's wrong?
Variable name can'be MAX, it is reserved for the function with the same name. Change it to e.g. v_max_seats.
Apart from that, it seems that you're selecting from the seat_allocation table (line #8), while the trigger fires on insert on the same table. It'll cause the mutating table error so - you'll have to do something. Nowadays, it is a compound trigger that fixes that. If your database version doesn't support it, you'll use a package. There are examples on the Internet.
Also, why using a subquery? What's wrong with e.g.
select max_seats into v_max_seats from programme_code where prog_code = :new.prog_code

Trigger to monitor is value acceptable or not

I have Oracle 11g and a table called CODES and there is column ID and CODESA as follow:
ID CODESA
1 9999
1 8889
2 77777
2 99999
3 1234
3 4321
4 565656
etc.
Then I need to update another table CODES2 and column CODESB based on ID in CODES table
I need a trigger to monitor this.
Let´s say I monitoring ID = 2 with this trigger and all different CODESA´s under that ID,
you can see that only these are possible to update in CODESB
2 77777
2 99999
How to make a trigger to launch if user is trying to enter some code in CODESB
which is for example from ID = 3 ?
Appreciate your help. Thanks,
Some_user
#APC is correct. We can use foreign key but lets say OP dont want those columns to be primary or unique, in that case trigger is the solution.
Create or replace trigger codes2_trg
Before insert or update On codes2
For each row
Declare
Cnt number;
Begin
Select count(1) into cnt
From codes where (id, codesa) = (:new.id, :new.codesb);
If cnt = 0 then
Raise_application_error('-20001', 'these balues are not allowed.');
End if;
End;
/
Cheers!!

For loop - insert blank rows in ORACLE

I am looking to insert blank records into a table to get a final value of 57,816,000 records. I am starting with a table of 550 unique identifiers and for each distinct TMC name and i want to add 105,119 records for each distinct value. So each TMC would have 105,120 records. (105,119 * 550 = 57,815,450 (+ original 550 = 57,816,000))
However, the problem i am having is an error within TOAD saying this.
ORA-03113: end-of-file on communication channel
Process ID: 10272
Session ID: 247 Serial number: 1959
Script will end
It works on a small scale but i suspect its not the best way to go. Below is my script. Any advice?
declare i number(10) :=1;
begin
for i in 1..105119
Loop
insert into npmrds_dummy
select distinct tmc,
travel_time_passenger_vehicles,
travel_time_freight_trucks,
travel_time_all_vehicles,
road_number,
road_name,
epoch,
distance,
date1,
admin_level_1,
admin_level_2,
admin_level_3
from npmrds_dummy;
end loop;
end;
You could do this with one SQL statement:
insert into npmrds_dummy
select npmrds_dummy.*
from npmrds_dummy
inner join ( select 1 from dual connect by level <= 105119 )
The join with the sub select is a neat trick to multiply the number of records.
As at the start your records are unique, there is no need for the distinct, and you can just do select npmrds_dummy.*.

PL/SQL select returns more than one line

I'm embarrassed to admit this is a totally noob question - but I take shelter in the fact that I come from a T-SQL world and this is a totally new territory for me
This is a simple table I have with 4 records only
ContractorID ProjectID Cost
1 100 1000
2 100 800
3 200 1005
4 300 2000
This is my PL SQL function which should take a contractor and a project id and return number of hours ( 10 in this case )
create or replace FUNCTION GetCost(contractor_ID IN NUMBER,
project_ID in NUMBER)
RETURN NUMBER
IS
ContractorCost NUMBER;
BEGIN
Select Cost INTO ContractorCost
from Contractor_Project_Table
where ContractorID= contractor_ID and ProjectID =project_ID ;
return ContractorCost;
END;
But then using
select GetCost(1,100) from Contractor_Project_Table;
This returns same row 4 times
1000
1000
1000
1000
What is wrong here? WHy is this returning 4 rows instead of 1
Thank you for
As #a_horse_with_no_name points out, the problem is that Contractor_Project_Table has (presumably) 4 rows so any SELECT against Contractor_Project_Table with no WHERE clause will always return 4 rows. Your function is getting called 4 times, one for each row in the table.
If you want to call the function with a single set of parameters and return a single row of data, you probably want to select from the dual table
SELECT GetCost( 1, 100 )
FROM dual
Because you have 4 rows in Contractor_Project_Table table. Use this query to get one record.
select GetCost(1,100) from dual;

getting last record of a cursor

If I have a cursor cur which contain these records
DEPTNO ENAME ORD CNT
10 KING 1 3
10 CLARK 2 3
10 MILLER 3 3
20 JONES 1 5
I get my cursor record like this :
FOR i IN cur LOOP
--Process
END LOOP;
Now I need to enhance my process and do a check, if the value of CNT column of the last record is equal to 5 I don't need to navigate into this cursor.
Is there a way to directly get the last record of the cursor to test CNT column without looping ?
No. A cursor is a pointer to a program that executes the query. You can only fetch from the cursor. Oracle itself has no idea what the last row the cursor will return until you attempt to fetch a row and find there are no more rows to return.
You could, of course, modify the query so that the CNT of the last row is returned in a separate column (assuming that you have some way to order the rows so that the "last row" is a meaningful concept).

Resources