SQL Trigger Error ORA-04098 - sql

i have two tables named as childs and parent.
create table parent(
wallet_id NUMBER generated always as identity,
amount int,
customer_id int,
primary key(wallet_id),
Foreign key (customer_id) REFERENCES childs(customer_id)
);
create table childs(
customer_id number generated always as identity,
name varchar2 (255)
);
Now what i wanted to achieve was to get name from childs , and assign a wallet_id to childs in parent table as parent table has a foreign key to customer_id.
For this purpose i created a trigger.
create or replace
TRIGGER TRIGGER1
AFTER INSERT ON CHILDS
Declare
id int;
BEGIN
select MAX(customer_id) into id FROM childs;
insert into parent (customer_id ) values ( id );
END;
Now trigger is created but when i insert value in childs,
insert into childs(names) values ('jarral');
Now following error appears:
SQL Error: ORA-04098: trigger 'SYSTEM.TRG' is invalid and failed re-validation
04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation"
*Cause: A trigger was attempted to be retrieved for execution and was
found to be invalid. This also means that compilation/authorization
failed for the trigger.
*Action: Options are to resolve the compilation/authorization errors,
disable the trigger, or drop the trigger.
How can i solve that?

I'm not entirely sure I follow your question, but is this what you are after ?
SQL> create table t1 ( id number generated as identity , x int);
Table created.
SQL> create table t2 ( id number generated as identity , t1_id int);
Table created.
SQL>
SQL> create or replace
2 trigger trg
3 after insert on t1
4 for each row
5 begin
6 insert into t2 (t1_id) values ( :new.id);
7 end;
8 /
Trigger created.
SQL> insert into t1 (x) values ( 0);
1 row created.
SQL> select * from t1;
ID X
---------- ----------
1 0
SQL> select * from t2;
ID T1_ID
---------- ----------
1 1

Related

No matter what data I insert into my table, the date stays the same at 03.01.2022. How can I fix this?

I created a primitive table in which I can store date, time, the id of a patient and the id of an employee.
CREATE TABLE Squedule (
id INTEGER,
datee DATE NOT NULL,
timee CHAR(5),
patientId CHAR(10),
employeeId CHAR(10),
CONSTRAINT squedule_pk PRIMARY KEY (kennzahl),
CONSTRAINT squedule_fkSprstdh FOREIGN KEY (employeeId) REFERENCES Sprechstdhilfe,
CONSTRAINT squedule_fkPatientIn FOREIGN KEY (patientId) REFERENCES PatientIn);
------------------I insert the data like so
INSERT INTO squedule(datee,timee,patientid,employeeid) VALUES('02.02.3000','16:43',8137770103,3146213220);
------------------This is the trigger for the id
CREATE TRIGGER newSquedule BEFORE INSERT ON Squedule
FOR EACH ROW
BEGIN
SELECT auto_increment_pk.NEXTVAL
INTO :new.id
FROM dual;
END;
This worked just fine until I noticed that no matter what data I try to insert for the datee value it always ends up with '03.01.2022' in the table for every single insert.
I dropped all tables and created them again a few times, because a few system_sequences got created, I guess because of an Identity I use in another table. But they did not get deleted with dropping every single table.
Maybe one of them is triggering something.
What can I do to solve this problem? I am clueless...
I can't reproduce what you're saying.
I removed foreign keys from the table (as I didn't feel like creating tables you reference).
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> CREATE SEQUENCE auto_increment_pk;
Sequence created.
SQL> CREATE TABLE squedule
2 (
3 id INTEGER,
4 datee DATE NOT NULL,
5 timee CHAR (5),
6 patientid CHAR (10),
7 employeeid CHAR (10),
8 CONSTRAINT squedule_pk PRIMARY KEY (id)
9 );
Table created.
SQL> CREATE OR REPLACE TRIGGER newsquedule
2 BEFORE INSERT
3 ON squedule
4 FOR EACH ROW
5 BEGIN
6 :new.id := auto_increment_pk.NEXTVAL;
7 END;
8 /
Trigger created.
Inserts:
SQL> INSERT INTO squedule (datee,
2 timee,
3 patientid,
4 employeeid)
5 VALUES ('02.02.3000',
6 '16:43',
7 8137770103,
8 3146213220);
1 row created.
But, the way you put it, I can insert anything into the timee column, including such a rubbish:
SQL> INSERT INTO squedule (datee,
2 timee,
3 patientid,
4 employeeid)
5 VALUES ('25.02.3000',
6 'xy:83',
7 8137770103,
8 3146213220);
1 row created.
Result:
SQL> SELECT * FROM squedule;
ID DATEE TIMEE PATIENTID EMPLOYEEID
---------- ------------------- ----- ---------- ----------
1 02.02.3000 00:00:00 16:43 8137770103 3146213220 --> 02.02.3000, not 03.01.2022
2 25.02.3000 00:00:00 xy:83 8137770103 3146213220 --> invalid time value
SQL>
I suggest you abandon what you're doing and use only one column whose datatype is DATE as - in Oracle - it contains both date and time component. Something like this:
SQL> DROP TABLE squedule;
Table dropped.
SQL> CREATE TABLE squedule
2 (
3 id INTEGER,
4 datee DATE NOT NULL,
5 patientid CHAR (10),
6 employeeid CHAR (10),
7 CONSTRAINT squedule_pk PRIMARY KEY (id)
8 );
Table created.
SQL> CREATE OR REPLACE TRIGGER newsquedule
2 BEFORE INSERT
3 ON squedule
4 FOR EACH ROW
5 BEGIN
6 :new.id := auto_increment_pk.NEXTVAL;
7 END;
8 /
Trigger created.
Insert:
SQL> INSERT INTO squedule (datee, patientid, employeeid)
2 VALUES (TO_DATE ('02.02.3000 14:43', 'dd.mm.yyyy hh24:mi'),
3 8137770103,
4 3146213220);
1 row created.
SQL> SELECT * FROM squedule;
ID DATEE PATIENTID EMPLOYEEID
---------- ------------------- ---------- ----------
3 02.02.3000 14:43:00 8137770103 3146213220
SQL>

Update table after delete using trigger

As the title states, I'm trying to use a trigger to update a value in Table2 when a row gets deleted from Table1. My code looks like this:
CREATE TRIGGER TRG_Table1_DEL
ON Table1
FOR DELETE
AS
UPDATE Table2 SET
FK_Table1ID = NULL
WHERE FK_Table1ID = (SELECT Table1ID FROM DELETED)
The first error I get is with the UPDATE command and that states:
"Incorrect syntax near 'UPDATE'. Expecting EXTERNAL.
The second error
is with the DELETED table that I'm trying to access. This states
"Invalid object name 'DELETED'.
Overall, I'm just trying to mimic a constraint that sets the column to null (ON DELETE SET NULL). I'm doing this because I got an error saying I might cause multiple cycles or cascade paths when trying to add the constraint.
For my code, I based it off this answer.
This should work in SQL Server. I have just replaced (=) with (in).
CREATE TRIGGER TRG_Table1_DEL
ON Table1
FOR DELETE
AS
UPDATE Table2
SET FK_Table1ID = NULL
WHERE FK_Table1ID IN (SELECT Table1ID FROM DELETED)
Example:
create table empsalary(empid int, month int , salary int);
insert into empsalary values(1, 1, 100);
insert into empsalary values(1, 2, 101);
insert into empsalary values(1, 3, 103);
create table emp(empid int, id int);
insert into emp values(1,1);
CREATE TRIGGER TRG_Table1_DEL
ON empsalary
FOR DELETE
AS
UPDATE emp
SET id = NULL
WHERE empid IN (SELECT empid FROM DELETED)
select * from empsalary
empid
month
salary
1
1
100
1
2
101
1
3
103
select * from emp
empid
id
1
1
delete empsalary where month=1;
select * from empsalary;
empid
month
salary
1
2
101
1
3
103
select *from emp;
empid
id
1
null
db<>fiddle here
The problem turned out to have a very simple fix. I was getting the errors because I was trying to add the trigger after dropping a constraint. This is fine, but I forgot to add a GO command in between the dropping of the constraint and the creation of the trigger. My code looked like this:
DROP CONSTRAINT
ADD TRIGGER
but this was the correct solution:
DROP CONSTRAINT
GO
ADD TRIGGER
Edit: as DaleK has pointed out, I also need to modify the WHERE clause in case the DELETED table has multiple rows

Oracle SQL Trigger Syntax

I am trying to create a trigger that checks if the faculty member to be added to the assigned table will is already on the qualified table for a specified class. Perhaps this is a tedious method. Nevertheless, I'd still like to know what I'm doing wrong. The following is my code with created the created tables and the trigger being the last part of the code:
CODE:
CREATE TABLE Faculty (
FId varchar(10),
FName varchar(20),
CONSTRAINT Faculty_ID_pk PRIMARY KEY(FId)
);
CREATE TABLE Course (
CId varchar(10),
CName varchar(20),
CONSTRAINT Course_ID_pk PRIMARY KEY(CId)
);
CREATE TABLE Qualify (
QDate DATE,
FId varchar(10),
CId varchar(10),
CONSTRAINT Qualifying_date CHECK(QDate >= TO_DATE('2020-08-24', 'YYYY-MM-DD')),
CONSTRAINT Qualify_FID_fk FOREIGN KEY(FId) REFERENCES Faculty(FId),
CONSTRAINT Qualify_CID_fk FOREIGN KEY(CId) REFERENCES Course(CId)
);
CREATE TABLE Assign (
ADate DATE,
FId varchar(10),
CId varchar(10),
CONSTRAINT Qualifying_check CHECK(ADate > TO_DATE('2020-08-24', 'YYYY-MM-DD')),
CONSTRAINT Assign_FID_fk FOREIGN KEY(FId) REFERENCES Faculty(FId),
CONSTRAINT Assign_CID_fk FOREIGN KEY(CId) REFERENCES Course(CId)
);
CREATE OR REPLACE TRIGGER Check_If_Qualified
BEFORE INSERT ON Assign
FOR EACH ROW
DECLARE
v_facNum number;
BEGIN
SELECT f.FId
into v_facNum
from Faculty f
where f.facnum = :new.fid;
END;
However, I keep receiving an error saying:
Error at line 7: PLS-00225: subprogram or cursor 'F' reference is out of scope
v_facNum number;
BEGIN
SELECT f.FId
into v_facNum
from Faculty f
Does anyone know what could be wrong?
There are lots of issues in your code. You can check the count of records into FACULTY table and use that count for whatever logic you want.
CREATE OR REPLACE TRIGGER CHECK_IF_QUALIFIED
BEFORE INSERT ON ASSIGN
FOR EACH ROW
DECLARE
CNT NUMBER;
BEGIN
SELECT COUNT(1)
INTO CNT
FROM FACULTY
WHERE FACNUM = :NEW.FID;
END;
/
That would be something like this (sample tables are really just a sample; they are here to make the trigger compile):
SQL> create table assign (fid number);
Table created.
SQL> create table faculty (facnum number, fid number);
Table created.
SQL> CREATE OR REPLACE TRIGGER Check_If_Qualified
2 BEFORE INSERT ON Assign
3 FOR EACH ROW
4 DECLARE
5 v_facNum number;
6 BEGIN
7 SELECT f.FId
8 into v_facNum
9 from Faculty f
10 where f.facnum = :new.fid;
11
12 -- now do something with v_facNum
13 END;
14 /
Trigger created.
SQL>

how to add trigger to count number of rows automatically after inserting in oracle sql developer

I want to add trigger to count number of movies after inserting!
This is the table to store the count value:
CREATE TABLE mov_count
(mcount NUMBER);
and the movie table:
create table movie
(mov_id number primary key,
mov_title varchar(20),
mov_lang varchar(20));
This is the trigger I have created:
create trigger count_movie_trg
after insert on movie
for each row
BEGIN
UPDATE mov_count
SET mcount = (SELECT COUNT(*) FROM movie);
END;
/
After creating this i tried to add movie but its showing mutating trigger/function may not see it error.
It is the FOR EACH ROW that bothers you. It is a table-level trigger, so:
Enter a dummy value for beginning (as you'll update it later):
SQL> insert into mov_count values (0);
1 row created.
Trigger:
SQL> create or replace trigger count_movie_trg
2 after insert on movie
3 begin
4 update mov_count c set
5 c.mcount = (select count(*) from movie m);
6 end;
7 /
Trigger created.
Testing:
SQL> insert into movie
2 select 1, 'Titanic' from dual union all
3 select 2, 'Superman' from dual;
2 rows created.
SQL> select count(*) from mov_count;
COUNT(*)
----------
1
SQL>
Why not just maintain the value without referring to the original table?
create trigger count_movie_trg after insert on movie for each row
begin
update mov_count set mcount = mcount + 1;
end;
To keep the count up-to-date, you'll need a delete trigger as well.
Don't use the table at all; use a view instead.
CREATE VIEW mov_count ( mcount ) AS
SELECT COUNT(*) FROM movie;
db<>fiddle

PL/SQL: Creating a Trigger on one table to update the item quantity contained within a separate table

I'm trying to create a trigger that updates the in stock quantity of a tool when the tool is returned, and also print a message stating the tool's new quantity in stock. I have two tables: Tool (stores tool info, including in stock quantity) and Rental (stores rental transaction information, including the date/time it was returned).
The returned_time column remains NULL until the tool is returned. I've created a trigger that fires when the return_time is updated to a value other than NULL. Below is my code for creating the trigger:
create or replace trigger update_quantity_trigger
after update of return_time on rental
for each row when (old.return_time is null and new.return_time is not null)
declare
t_name tool.tname%type; --tool name variable
t_quantity tool.quantity%type; --tool quantity variable
begin
update tool set quantity = quantity + 1
where tid = :new.tid;
select tname into t_name
from tool t
where tid = :new.tid;
select quantity into t_quantity
from tool t
where tid = :new.tid;
dbms_output.put_line('The quantity of ' || t_name || 's is now ' || t_quantity);
end;
I'm just tested with this simple update statement
update rental set return_time = systimestamp
where rid = 5;
After running the code to create the trigger, I receive the message "TRIGGER_UPDATE_QUANTITY compiled" without any errors; however, after executing the update statement, I get the following error:
"SQL Error: ORA-04098: trigger 'TOOL_QUANTITY_UPDATE_TRIGGER' is invalid and failed re-validation
04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation"
*Cause: A trigger was attempted to be retrieved for execution and was
found to be invalid. This also means that compilation/authorization
failed for the trigger.
*Action: Options are to resolve the compilation/authorization errors,
disable the trigger, or drop the trigger."
If I drop the trigger, the update statement works as expected. Any ideas what's causing this error? I assume it's an issue with my statements in the body of my trigger; however, I cannot seem to rectify it.
For reference, here are the tables created along with some sample records
create table tool
(tid int, --- tool id
tname varchar(50), -- tool name
ctid int, --- category id
quantity int,
primary key (tid),
foreign key (ctid) references category
);
insert into tool values(1,'21 inch electric mower',2,2);
insert into tool values(2,'30 inch large gasoline mower',3,2);
insert into tool values(3,'small carpet cleaner',4,2);
insert into tool values(4,'large carpet cleaner',4,2);
create table rental
(
rid int, --- rental id
cid int, --- customer id
tid int, --- tool id
tuid int, --- time unit id
num_unit int, --- number of units, if unit = 1 hour, num_unit = 5 means 5 hours.
start_time timestamp, -- rental start time
end_time timestamp, --- suppose rental end_time
return_time timestamp,--- actual return time
credit_card varchar(20),
total number, --- total charge
primary key (rid),
foreign key(cid) references cust,
foreign key(tid) references tool,
foreign key(tuid) references time_unit
);
insert into rental values(1,1,1,1,4,timestamp '2019-08-01
10:00:00.00',null,null,'123456789',null);
insert into rental values(2,2,3,2,1,timestamp '2019-08-11
10:00:00.00',null,null,'123456789',null);
insert into rental values(3,2,1,1,5,timestamp '2019-08-12
21:00:00.00',null,null,'123456789',null);
insert into rental values(4,3,3,1,4,timestamp '2019-08-13
19:00:00.00',null,null,'12222828828',null);
insert into rental values(5,3,3,1,4,timestamp '2019-08-13
19:00:00.00',null,null,'12222828828',null);
Are you sure the error is on this trigger, and not an earlier version. Your error message references trigger TOOL_QUANTITY_UPDATE_TRIGGER but the posted trigger is "update_quantity_trigger". Those are not the same object. BTW you can reduce the trigger to a single SQL statement by using the return clause on the update:
create or replace trigger update_quantity_trigger
after update of return_time on rental
for each row when (old.return_time is null and new.return_time is not null)
declare
t_name tool.tname%type; --tool name variable
t_quantity tool.quantity%type; --tool quantity variable
begin
update tool set quantity = quantity + 1
where tid = :new.tid
returning tname, quantity
into t_name, t_quantity;
dbms_output.put_line('The quantity of ' || t_name || 's is now ' || t_quantity);
end;
Thank you for sample data. I created tables (by removing foreign key constraints as I don't have those tables):
SQL> create table tool
2 (tid int, --- tool id
3 tname varchar(50), -- tool name
4 ctid int, --- category id
5 quantity int,
6 primary key (tid)
7 );
Table created.
SQL> insert into tool values(1,'21 inch electric mower',2,2);
1 row created.
SQL> insert into tool values(2,'30 inch large gasoline mower',3,2);
1 row created.
SQL> insert into tool values(3,'small carpet cleaner',4,2);
1 row created.
SQL> insert into tool values(4,'large carpet cleaner',4,2);
1 row created.
SQL> create table rental
2 (
3 rid int, --- rental id
4 cid int, --- customer id
5 tid int, --- tool id
6 tuid int, --- time unit id
7 num_unit int, --- number of units, if unit = 1 hour, num_unit = 5 means 5 hours.
8 start_time timestamp, -- rental start time
9 end_time timestamp, --- suppose rental end_time
10 return_time timestamp,--- actual return time
11 credit_card varchar(20),
12 total number, --- total charge
13 primary key (rid)
14 );
Table created.
SQL> insert into rental values(1,1,1,1,4,timestamp '2019-08-01 10:00:00.00',null,null,'123456789',null);
1 row created.
SQL> insert into rental values(2,2,3,2,1,timestamp '2019-08-11 10:00:00.00',null,null,'123456789',null);
1 row created.
SQL> insert into rental values(3,2,1,1,5,timestamp '2019-08-12 21:00:00.00',null,null,'123456789',null);
1 row created.
SQL> insert into rental values(4,3,3,1,4,timestamp '2019-08-13 19:00:00.00',null,null,'12222828828',null);
1 row created.
SQL> insert into rental values(5,3,3,1,4,timestamp '2019-08-13 19:00:00.00',null,null,'12222828828',null);
1 row created.
SQL>
Trigger:
SQL> create or replace trigger update_quantity_trigger
2 after update of return_time on rental
3 for each row when (old.return_time is null and new.return_time is not null)
4 declare
5 t_name tool.tname%type; --tool name variable
6 t_quantity tool.quantity%type; --tool quantity variable
7 begin
8 update tool set quantity = quantity + 1
9 where tid = :new.tid;
10
11 select tname into t_name
12 from tool t
13 where tid = :new.tid;
14
15 select quantity into t_quantity
16 from tool t
17 where tid = :new.tid;
18 dbms_output.put_line('The quantity of ' || t_name || 's is now ' || t_quantity);
19 end;
20 /
Trigger created.
SQL>
Testing:
SQL> select rid, cid, return_time from rental;
RID CID RETURN_TIME
---------- ---------- ------------------------------
1 1
2 2
3 2
4 3
5 3
SQL> update rental set return_time = systimestamp where rid = 5;
The quantity of small carpet cleaners is now 3
1 row updated.
SQL> select rid, cid, return_time from rental;
RID CID RETURN_TIME
---------- ---------- ------------------------------
1 1
2 2
3 2
4 3
5 3 21.11.19 08:53:46,073000
SQL>
In other words, it works on my 11g XE.