Oracle express edition 10g trigger problem at runtime - plsql

Below image is showing error.
error screenshot
I have created this simple trigger in plsql.
CREATE OR REPLACE TRIGGER TR6
BEFORE UPDATE ON EMPLOYEE
FOR EACH ROW
BEGIN
INSERT INTO PRAC14 (EMP_NO,EMP_NAME,EMP_SAL,DEPT_NO)
VALUES(:OLD.EMP_NO,:OLD.EMP_NAME,:OLD.EMP_SAL,:OLD.DEPT_NO);
END;
/
after running above code it shows TRIGGER CREATED.
Then when I am updating my employee table like
UPDATE EMPLOYEE
SET EMP_SAL=3000
WHERE DEPT_NO=10
I am getting this error message
ORA-04098: trigger 'Username.TR' is invalid and failed re-validation.I am using Oracle database 10g express edition.

Note the difference:
CREATE OR REPLACE TRIGGER TR6
---
vs.
ORA-04098: trigger 'Username.TR' is invalid
--
It seems that there's yet another trigger on that table which is invalid. Either fix it, or drop it.
Check triggers by running
select table_name, trigger_name, trigger_type from user_triggers order by 1, 2;
[Example]
It is based on Scott's EMP table. Trigger intentionally uses :old.empnox, a column which doesn't exist. It leads to error you got:
SQL> create table prac14 as select empno, ename, sal, deptno
2 from emp where 1 = 2;
Table created.
SQL>
SQL> create or replace trigger tr6
2 before update on emp
3 for each row
4 begin
5 insert into prac14 (empno,ename,sal,deptno)
6 values(:old.empnox,:old.ename,:old.sal,:old.deptno);
7 end;
8 /
Warning: Trigger created with compilation errors.
SQL>
SQL> update emp set sal = 3000 where deptno = 10;
update emp set sal = 3000 where deptno = 10
*
ERROR at line 1:
ORA-04098: trigger 'SCOTT.TR6' is invalid and failed re-validation
But, if trigger code is fixed, everything runs OK:
SQL> create or replace trigger tr6
2 before update on emp
3 for each row
4 begin
5 insert into prac14 (empno,ename,sal,deptno)
6 values(:old.empno,:old.ename,:old.sal,:old.deptno);
7 end;
8 /
Trigger created.
SQL>
SQL> update emp set sal = 3000 where deptno = 10;
3 rows updated.
SQL>
I suggest you post the same, executed in your database.

I have created multiple trigger for DML operation on a single table. That is why I am getting error. I have dropped all other triggers on EMPLOYEE table except TR6 and it worked.
Kudos to you #Littlefoot.

Related

PLSQL Return Sequence.currval When Sequence Name Is Built Using Substitution Strings

I would like to use the same application in different instances so I need to specify the workspace and sequence ID.
Example query
BEGIN
INSERT INTO STEP (STEP_CHART_TITLE)
VALUES ('Action', 'Action');
RETURN '"'||:v_workspace||'"."'||:v_seqid||'".currval';
END;
If I use:
"FREEADMIN"."ISEQ$$_111997".currval;
in the return statement it works fine.
If I use the substitution strings, it will build the string correctly, but won't return the sequence number.
Is there a way to get the sequence number?
Thanks
"PL/SQL" as Oracle's procedural extension to SQL? Asking because I don't quite understand what "workspace" represents (we call it a "user" or a "schema" or even "owner" in Oracle).
If so, then you can't fetch current value unless you first fetch next sequence value (you didn't post whole code you use so I'm not sure whether you did that or not; also, insert statement is wrong - you're inserting 2 values into a single column).
SQL> select seq.currval from dual;
select seq.currval from dual
*
ERROR at line 1:
ORA-08002: sequence SEQ.CURRVAL is not yet defined in this session
SQL> select seq.nextval from dual;
NEXTVAL
----------
6
SQL> select seq.currval from dual;
CURRVAL
----------
6
SQL>
Therefore, the whole code might look like this - you'd use dynamic SQL. As this is SQL*Plus, I'm using substitution variables; you'd use bind variables (i.e. :v_workspace instead of '&v_workspace') (if that's what you're doing). This code just displays the value - you'd return it.
SQL> create table step (id number, step_chart_title varchar2(10));
Table created.
SQL> declare
2 l_str varchar2(200);
3 l_id number;
4 begin
5 l_str := 'select ' || '&v_workspace' ||'.'|| '&v_seqid' ||'.nextval from dual';
6 execute immediate l_str into l_id;
7
8 insert into step (id, step_chart_title) values (l_id, 'Action');
9
10 dbms_output.put_line(l_id); --> L_ID now contains CURRVAL
11 end;
12 /
Enter value for v_workspace: scott
Enter value for v_seqid: seq
8 --> here it is
PL/SQL procedure successfully completed.
SQL>

ORA-4088, ORA-6512 Using Triggers and RAISE_APPLICATION_ERROR

While trying to Enforce Foreign Key Integrity in Oracle with Trigger
CREATE OR REPLACE TRIGGER TRG_IU_SPONSORID_user_registration
BEFORE INSERT OR UPDATE OF U_SPONSORID ON user_registration
FOR EACH ROW
DECLARE l_SPONSORID VARCHAR2 (2000);
BEGIN
SELECT U_SPONSORID
Into l_SPONSORID
FROM U_SPONSOR WHERE U_SPONSORID = :NEW.U_SPONSORID;
If l_SPONSORID is null
THEN raise_application_error(-20010, 'Not a valid SPONSORID: '|| ':NEW.U_SPONSORID');
End if;
END;
I am getting the following errors, while raise error message is not printing
ORA-6512: at "BPORTD1.TRG_IU_SPONSOR_USER_REGISTRATION", line 3
ORA-4088: error during execution of trigger 'BPORTD1.TRG_IU_SPONSOR_USER_REGISTRATION'
​Any idea of why is this happening?
Code you wrote has 1.5 mistakes:
1st: if there's no such row in U_SPONSOR table, select won't return NULL as you thought, but no_data_found you should handle; I presume that's what happened to you
0.5th: remove single quotes from ':new.u_sponsorid' in dbms_output.put_line as you'll display literally that, not the ID value.
Sample tables and trigger:
SQL> create table u_sponsor (u_sponsorid number);
Table created.
SQL> create table user_registration(u_sponsorid number);
Table created.
SQL> create or replace trigger trg_iu_sponsor
2 before insert or update of u_sponsorid on user_registration
3 for each row
4 declare
5 l_sponsorid varchar2 (2000);
6 begin
7 select u_sponsorid
8 into l_sponsorid
9 from u_sponsor
10 where u_sponsorid = :new.u_sponsorid;
11 exception
12 when no_data_found then
13 raise_application_error(-20010,
14 'Not a valid SPONSORID: '|| :new.u_sponsorid);
15 end;
16 /
Trigger created.
Testing: master row first:
SQL> insert into u_sponsor values (200);
1 row created.
Two details:
SQL> insert into user_registration values (100);
insert into user_registration values (100)
*
ERROR at line 1:
ORA-20010: Not a valid SPONSORID: 100
ORA-06512: at "SCOTT.TRG_IU_SPONSOR", line 10
ORA-04088: error during execution of trigger 'SCOTT.TRG_IU_SPONSOR'
SQL> insert into user_registration values (200);
1 row created.
SQL>
However, I guess you used a trigger to enforce referential integrity just for educational purposes, because - if you want to do that properly, create a foreign key constraint. Something like this:
SQL> create table u_sponsor (u_sponsorid number primary key);
Table created.
SQL> create table user_registration(u_sponsorid number references u_sponsor);
Table created.
SQL> insert into u_sponsor values (200);
1 row created.
SQL> insert into user_registration values (100);
insert into user_registration values (100)
*
ERROR at line 1:
ORA-02291: integrity constraint (SCOTT.SYS_C009854) violated - parent key not found
SQL> insert into user_registration values (200);
1 row created.
SQL>

Deleting a record in parent table and updating "DELETED" column in child table

I have a parent table(profiles) in which profile_id is the primary key and is a foreign key to 3 different child tables. (s_profile, p_profile, c_profile)
Now, i want to delete a record from the table profile and want to update a "DELETED" column in the child tables with sysdate.
However my script doesn't allow it saying "Foreign key violated- Child record found".
Is there a solution to it?
What is the purpose of that foreign key constraint, if you want to allow deleting master while details exist?
Anyway, here's an example which shows what you might do; is it the right way, I can't tell (I suspect not - once again, it is cancels the purpose of the referential constraint).
Create two tables - master and its detail:
SQL> create table profiles
2 (id_profile number primary key);
Table created.
SQL> create table s_profile
2 (id number primary key,
3 id_profile number constraint fk_s_pro references profiles (id_profile),
4 deleted date);
Table created.
SQL>
Sample data and attempt to delete a master while detail exists:
SQL> insert into profiles values (1);
1 row created.
SQL> insert into s_profile (id, id_profile) values (100, 1);
1 row created.
SQL> delete from profiles where id_profile = 1;
delete from profiles where id_profile = 1
*
ERROR at line 1:
ORA-02292: integrity constraint (SCOTT.FK_S_PRO) violated - child record found
SQL>
Create a trigger on the master table which removes foreign key value and sets the date:
SQL> create or replace trigger trg_bd_prof
2 before delete on profiles
3 for each row
4 begin
5 update s_profile s set
6 s.id_profile = null,
7 s.deleted = sysdate
8 where s.id_profile = :old.id_profile;
9 end;
10 /
Trigger created.
Let's try to delete master again:
SQL> delete from profiles where id_profile = 1;
1 row deleted.
SQL> select * From s_profile;
ID ID_PROFILE DELETED
---------- ---------- ----------
100 2018-10-03
SQL>
If you want to save foreign key value, you could alter detail table and add another column, say deleted_id_profile and populate it with the same trigger. Though, what would you do with it, if parent doesn't exist any more and you can't find any info about it?

PLSQL_trigger cannot be complied

I need to create a trigger that when the last employee of the dept is deleted from emp table, the dept is deleted from the dept table.
emp(empno, ename, deptno)
dept(deptno, dname)
First, I created a procedure that deletes the dept from dept table given a deptno.
CREATE OR REPLACE PROCEDURE del_dept
(v_dno in number)
is
begin
delete from DEPT where deptno = v_dno;
end;
Then I created a trigger that deletes the dept when the last emp in that dept is deleted. I tried to test the trigger by deleting one of the three emps in deptno10, but I got error mesg from command that trigger is invalid and failed re-validation.
create or replace trigger del_dept
after delete on EMP
for each row
DECLARE
emp_count Number;
g_dno Number;
begin
SELECT COUNT(:old.ename) INTO emp_count FROM emp group by deptno;
FOR i IN 1.. emp_count LOOP
IF i = emp_count THEN
del_dept(g_dno);
end if;
END LOOP;
End;
Error trigger is invalid and failed re-validation specifies that yor trigger was created with compilation error hence you were not able to test it. This is not a good idea to write a trigger in your case. I can see few issues in you code. So lets first resolve these issues.
When you write the code below, your trigger would be compiled and would be a valid one. So you will not get the error trigger is invalid and failed re-validation
CREATE OR REPLACE TRIGGER del_dept
AFTER DELETE
ON EMP
FOR EACH ROW
DECLARE
EMP_CNT NUMBER;
BEGIN
SELECT COUNT (1)
INTO emp_cnt
FROM emp
WHERE deptno = :old.deptno;
IF emp_cnt = 0
THEN
---del_dept is your procedure to delete records from dept table
del_dept (:old.deptno);
END IF;
END;
But when you would try to execute it you will further get the error:
ORA-04091: table EMP is mutating, trigger/function may not see it
ORA-06512: at "DEL_DEPT", line 4 ORA-04088: error during execution of
trigger 'DEL_DEPT'
The reason for getting this error is you are trying to select from the table from which you are deleting records and thats not allowed in oracle.
The best way for your case is to write a procedure which would delete the records once the last employee data is deleted from your dept table . See below:
CREATE OR REPLACE PROCEDURE del_dept (dept_no NUMBER)
IS
EMP_CNT NUMBER;
BEGIN
SELECT COUNT (1)
INTO emp_cnt
FROM emp
WHERE deptno = dept_no;
IF emp_cnt = 0
THEN
del_dept (dept_no);
END IF;
END;

Oracle Apex 5: Procedure not working for counter?

I'm trying to create a page counter. everytime someone enters a page a procedure is executed. 1 is added to the column check_count. Unfortunately Oracle Apex 5 is saying
ORA-24344: success with compilation error.
Why do you think that is?
CREATE OR REPLACE PROCEDURE check_counter(person IN varchar2) IS
count pageTable.check_count%type;
countTwo pageTable.check_count%type;
BEGIN
SELECT check_count INTO count FROM pageTable
WHERE person = pageTable.person_name;
countTwo := count + 1;
INSERT INTO pageTable (check_count)
VALUES(countTwo);
END;

Resources