Sql trigger not functioning - sql

CREATE OR REPLACE TRIGGER STUDENT
BEFORE INSERT
ON STUDENT
FOR EACH ROW
BEGIN
IF :NEW.ENO =NULL THEN
RAISE_APPLICATION_ERROR(-21900, 'ENROLL_NO IS MISSING');
END IF;
END;
So this was my trigger definition
But when I try to NUll values its accepted
I'm learning

It is not = null, but is null:
SQL> CREATE OR REPLACE TRIGGER trg_bi_student
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 IF :NEW.ENO is NULL THEN
6 RAISE_APPLICATION_ERROR(-21900, 'ENROLL_NO IS MISSING');
7 END IF;
8 END;
9 /
Trigger created.
SQL> insert into student (eno, name) values (1, 'Little');
1 row created.
SQL> insert into student (eno, name) values (null, 'Foot');
insert into student (eno, name) values (null, 'Foot')
*
ERROR at line 1:
ORA-21000: error number argument to raise_application_error of -21900 is out of
range
ORA-06512: at "SCOTT.TRG_BI_STUDENT", line 3
ORA-04088: error during execution of trigger 'SCOTT.TRG_BI_STUDENT'
SQL>
Though, why trigger? That's a not null constraint (most probably a primary key):
SQL> drop table student;
Table dropped.
SQL> create table student (eno number constraint pk_student primary key,
2 name varchar2(10));
Table created.
SQL> insert into student (eno, name) values (1, 'Little');
1 row created.
SQL> insert into student (eno, name) values (null, 'Foot');
insert into student (eno, name) values (null, 'Foot')
*
ERROR at line 1:
ORA-01400: cannot insert NULL into ("SCOTT"."STUDENT"."ENO")
SQL>
As of your second trigger (posted in a comment): if you show errors, then:
SQL> CREATE OR REPLACE TRIGGER TOTALMARKS
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 :NEW.TOTAL: =:NEW.S1+:NEW.S2+:NEW.S3;
6 DBMS_OUTPUT.PUT_LINE('TOTAL="| | :NEW. TOTAL) ;
7 END;
8 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER TOTALMARKS:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/11 PLS-00103: Encountered the symbol " " when expecting one of the
following:
:= . ( # % ; indicator
SQL>
This is the 2nd line in excecutable part of the trigger:
:NEW.TOTAL: =:NEW.S1+:NEW.S2+:NEW.S3;
1234567890123456
^
|
11th character
It says that you should've used := and not : = (i.e. no space in between), but then you get another error:
SQL> CREATE OR REPLACE TRIGGER TOTALMARKS
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 :NEW.TOTAL :=:NEW.S1+:NEW.S2+:NEW.S3;
6 DBMS_OUTPUT.PUT_LINE('TOTAL="| | :NEW. TOTAL) ;
7 END;
8 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER TOTALMARKS:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/22 PLS-00103: Encountered the symbol "TOTAL="| | :NEW. TOTAL) ;
END;" when expecting one of the following: (...)
You can't enclose strings into double quotes - use single ones. But, there's another error (consecutive pipe sign for concatenation), and yet another (no space between :new and .total), until finally it compiles:
SQL> CREATE OR REPLACE TRIGGER TOTALMARKS
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 :NEW.TOTAL :=:NEW.S1+:NEW.S2+:NEW.S3;
6 DBMS_OUTPUT.PUT_LINE('TOTAL='|| :NEW.TOTAL) ;
7 END;
8 /
Trigger created.
SQL>

Related

"ORA-04073: column list not valid for this trigger type" Error in Trigger creation

I want to write a trigger then give an error when IDPRODUCT=3 or IDPRODUCT=9 AND QUANTITY<10. If this condition is true then it have to give "Please enter quantity greater than 10." But it is not working and give me error.
Here is my trigger: This trigger is to check during insertion in table BB_BASKETITEM.
CREATE OR REPLACE TRIGGER User_defined_error
BEFORE INSERT OF IDPRODUCT,QUANTITYON BB_BASKETITEM
FOR EACH ROW
BEGIN
IF:NEW.IDPRODUCT=3 OR NEW.IDPRODUCT=9 AND NEW.QUANTITY<10 THEN
DBMS_OUTPUT.PUT_LINE(' Please enter quantity greater than 10. ');
END IF;
END;
/
Error:
Error report -
ORA-04073: column list not valid for this trigger type
04073. 00000 - "column list not valid for this trigger type"
*Cause: A column list was specified for a non-update trigger type.
*Action: Remove the column list.
As Oracle says: column list is invalid for this trigger type. Just omit it.
Sample table and trigger:
SQL> create table bb_basketitem (idproduct number, quantity number);
Table created.
SQL> create or replace trigger user_defined_error
2 before insert on bb_basketitem
3 for each row
4 begin
5 if (:new.idproduct = 3 or :new.idproduct = 9)
6 and :new.quantity < 10
7 then
8 raise_application_error(-20000, 'Please enter quantity greater than 10.');
9 end if;
10 end;
11 /
Trigger created.
Testing:
SQL> insert into bb_basketitem(idproduct, quantity) values (3, 5);
insert into bb_basketitem(idproduct, quantity) values (3, 5)
*
ERROR at line 1:
ORA-20000: Please enter quantity greater than 10.
ORA-06512: at "SCOTT.USER_DEFINED_ERROR", line 5
ORA-04088: error during execution of trigger 'SCOTT.USER_DEFINED_ERROR'
SQL> insert into bb_basketitem(idproduct, quantity) values (3, 20);
1 row created.
SQL>
Column list makes sense for before update trigger:
SQL> create or replace trigger trg_bu_bbb
2 before update of quantity on bb_basketitem
3 for each row
4 begin
5 if (:new.idproduct = 3 or :new.idproduct = 9)
6 and :new.quantity < 10
7 then
8 raise_application_error(-20001, 'Please enter quantity greater than 10.');
9 end if;
10 end;
11 /
Trigger created.
SQL> update bb_basketitem set quantity = 1;
update bb_basketitem set quantity = 1
*
ERROR at line 1:
ORA-20001: Please enter quantity greater than 10.
ORA-06512: at "SCOTT.TRG_BU_BBB", line 5
ORA-04088: error during execution of trigger 'SCOTT.TRG_BU_BBB'
SQL>

trigger in oracle that ensures that the value of ExpDate from the table ExpIt is less than or equal to the ERSubDate from the ExpReport

I am trying to create a trigger in oracle that ensures that the value of ExpDate from the table ExpIt is less than or equal to the ERSubDate from the ExpReport on INSERT and UPDATE statements that change the ExpDate in the ExpIt table.
When ran in the command prompt, the following comes up
warning: Trigger created with compilation errors.
Here is what I have tried so far, where am I going wrong?
Thank you in advance.
CREATE OR REPLACE TRIGGER Expense_Date
BEFORE INSERT OR UPDATE OF ExpDate
ON ExpIt
FOR EACH ROW
DECLARE
anExpDate ExpIts.ExpDate%TYPE;
anERSubDate ExpReport.ERSubDate%TYPE;
DateError EXCEPTION;
ExMessage VARCHAR(200);
BEGIN
SELECT ExpDate, ERSubDate
INTO anExpDate, anERSubDate
FROM ExpIt, ExpReport
WHERE ExpIt.ExpDate = :NEW.ExpDate;
IF anExpDate <= anERSubDate THEN
RAISE DateError;
END IF;
EXCEPTION
WHEN DateError THEN
ExMessage := ExMessage || 'Expense Date is Incorrect as it is after the Expense Report Submition date' ||
to_date(anExpDate);
raise_application_error(-20001, ExMessage);
END;
/
Before you go too far down this track - be aware that you generally cannot access the table you are triggering on from within the trigger itself.
In your case, your trigger is on EXPIT and you want to query EXPIT. That won't work.
Here's a trivial example of that:
SQL> create table t (x int );
Table created.
SQL> insert into t values (1);
1 row created.
SQL> commit;
Commit complete.
SQL>
SQL> create or replace
2 trigger TRG
3 before insert on T
4 for each row
5 declare
6 blah int;
7 begin
8 select count(*) into blah from t;
9 end;
10 /
Trigger created.
SQL>
SQL> insert into t values (2);
1 row created.
It looks fine, but in reality, there are plenty of cases where it will NOT work
SQL> insert into t
2 select rownum from dual
3 connect by level <= 5;
insert into t
*
ERROR at line 1:
ORA-04091: table MCDONAC.T is mutating, trigger/function may not see it
ORA-06512: at "MCDONAC.TRG", line 4
ORA-04088: error during execution of trigger 'MCDONAC.TRG'
This is a big topic, and more details on the issue and how to work around it are here
https://asktom.oracle.com/pls/apex/asktom.search?file=MutatingTable.html#presentation-downloads-reg

Multi line comment in oracle sqlplus

I have ran the below statements in sqlplus. It inserts duplicate of row 2. In log I have found that i row created after the comment line as well.
So, here I am asking the multi line comment should have a space between /* and comment and */ ?
insert into table values (1);
insert into table values (2);
/*comments here*/
insert into table values (3);
commit;
Log:
SQL> insert into table values (1);
1 row created.
SQL> insert into table values (2);
1 row created.
**SQL> /*comments here*/
1 row created.**
SQL> insert into table values (3);
1 row created.
select A from table;
A
------------
1
2
2
3
All,
I have tried in sqlplus. We need to give the space or new line between /* and following characters. So it treated as multi line comment.
correct syntax:
/* comments here */
or
/*
comments here
*/
Wrong syntax:
/*comments here*/
I presume that your code contains an extra forward slash. Have a look:
SQL> create table test (id number);
Table created.
SQL> insert into test values (1);
1 row created.
SQL> insert into test values (2);
1 row created.
SQL> /* comments
SQL> here
SQL> */
SQL> / --> this one; it executes the last command in buffer ...
1 row created. --> ... and results with yet another "2" begin inserted
SQL> insert into test values (3);
1 row created.
SQL> select * from test;
ID
----------
1
2
2
3
SQL>
Without it, everything is OK:
SQL> truncate table test;
Table truncated.
SQL> insert into test values (1);
1 row created.
SQL> insert into test values (2);
1 row created.
SQL> /* comments
SQL> here
SQL> */
SQL> insert into test values (3);
1 row created.
SQL> select * from test;
ID
----------
1
2
3
SQL>

How to allow oracle table column to have multiple rows in column but sames values only. Using Constraints

How to allow oracle table column to have multiple rows in column but same value only.
Create Table test ( col int);
case - I
insert into test values (1);
--should work
insert into test values (1);
--should work
insert into test values (2);
--Should throw error !!!!
case - II
truncate table test;
insert into test values (2);
--should work
insert into test values (2);
--Should work
insert into test values (1);
--Should throw error !!!!!!
If I have understood your requirement correctly, you can use before insert trigger. Check the value present in table, if new value matches with table value or table is having no data then only allow insert.
Here's the link about trigger
http://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm
UPDATE
Based on OP's two cases, I think a BEFORE INSERT TRIGGER would do the job:
Test case:
SQL> DROP TABLE TEST PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE test
2 ( col INT
3 );
Table created.
SQL>
SQL> CREATE OR REPLACE TRIGGER trg BEFORE
2 INSERT ON TEST FOR EACH ROW DECLARE ID NUMBER;
3 BEGIN
4 BEGIN
5 SELECT DISTINCT col INTO ID FROM TEST;
6 EXCEPTION
7 WHEN no_data_found THEN
8 NULL;
9 END;
10 IF :NEW.col <> id THEN
11 RAISE_APPLICATION_ERROR(-20001, 'Cannot Insert different value in the table');
12 END IF;
13 END;
14 /
Trigger created.
SQL>
The NO_DATA_FOUND exception is to ignore the first insert, since there would be no rows before that.
Now, let's test the INSERT statements:
CASE 1
SQL> INSERT INTO TEST VALUES (1);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (1);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (2);
INSERT INTO TEST VALUES (2)
*
ERROR at line 1:
ORA-20001: Cannot Insert different value in the table
ORA-06512: at "LALIT.TRG", line 10
ORA-04088: error during execution of trigger 'LALIT.TRG'
SQL>
CASE 2
SQL> TRUNCATE TABLE TEST;
Table truncated.
SQL>
SQL> INSERT INTO TEST VALUES (2);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (2);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (1);
INSERT INTO TEST VALUES (1)
*
ERROR at line 1:
ORA-20001: Cannot Insert different value in the table
ORA-06512: at "LALIT.TRG", line 10
ORA-04088: error during execution of trigger 'LALIT.TRG'
SQL>

Insert row to table B before updating it in table A

I have a table called applications and a table called application_history. I want to keep a history of applications and had the idea of using a trigger whenever a row gets updated in the applications table to copy that row to application_history before it is actually updated.
At the moment, I've written this code out from another SO post:
create or replace
trigger APPLICATION_UPDATE_TRG
BEFORE UPDATE ON TBL_APPLICATIONS
FOR EACH ROW
DECLARE
CURSOR curAppHistory IS
SELECT record_number, job_id, submitted_date, status_id, id
FROM tbl_application
WHERE id = :old.id;
vRowAppHistory curAppHistory%ROWTYPE;
BEGIN
OPEN curAppHistory;
FETCH curAppHistory INTO vRowAppHistory;
CLOSE curAppHistory;
INSERT INTO tbl_application_history
(record_number, job_id, submitted_date, status_id, application_id)
VALUES (vRowAppHistory.record_number, vRowAppHistory.job_id, vRowAppHistory.submitted_date,
vRowAppHistory.status_id, vRowAppHistory.id);
END;
However, it's not properly compiling. SQL Developer throws out 3 errors about commands not properly ended and statements being ignored.
What's the proper way to do this?
Edit: The errors:
Error(2,10): PLS-00341: declaration of cursor 'CURAPPHISTORY' is incomplete or malformed
Error(3,5): PL/SQL: SQL Statement ignored
Error(4,12): PL/SQL: ORA-00942: table or view does not exist
Error(6,18): PL/SQL: Item ignored
Error(9,3): PL/SQL: SQL Statement ignored
Error(9,28): PLS-00320: the declaration of the type of this expression is incomplete or malformed
Error(11,3): PL/SQL: SQL Statement ignored
Error(14,29): PLS-00320: the declaration of the type of this expression is incomplete or malformed
Error(14,44): PL/SQL: ORA-00984: column not allowed here
Error(4,12): PL/SQL: ORA-00942: table or view does not exist
A typo? You specified two different tables here.
BEFORE UPDATE ON TBL_APPLICATIONS
FROM tbl_application
Anyway, you'll get ORA-04091 with this trigger. Similar test case:
SYSTEM#dwal> create table t (key number primary key, value varchar2(10));
Table created.
SYSTEM#dwal> insert into t values (1, 'abcdef');
1 row created.
SYSTEM#dwal> insert into t values (2, 'ghijkl');
1 row created.
SYSTEM#dwal> commit;
Commit complete
SYSTEM#dwal> ed
Wrote file S:\\tools\buffer.sql
1 create or replace trigger tt
2 before update on t for each row
3 declare
4 cursor c is
5 select key, value
6 from t
7 where key = :old.key;
8 v c%rowtype;
9 begin
10 open c;
11 fetch c into v;
12 close c;
13 dbms_output.put_line(v.value);
14* end;
09:58:51 SYSTEM#dwal> /
Trigger created.
SYSTEM#dwal> update t set value = '123';
update t set value = '123'
*
ERROR at line 1:
ORA-04091: table SYSTEM.T is mutating, trigger/function may not see it
ORA-06512: at "SYSTEM.TT", line 3
ORA-06512: at "SYSTEM.TT", line 8
ORA-04088: error during execution of trigger 'SYSTEM.TT'
You should probably do it like this:
INSERT INTO tbl_application_history
(record_number, job_id, submitted_date, status_id, application_id)
VALUES
(:old.record_number, :old.job_id, :old.submitted_date, :old.status_id, :old.id);
The whole trigger would be a single insert statement in this case:
SYSTEM#dwal> create table t_log (key number, value varchar2(10));
Table created.
SYSTEM#dwal> ed
Wrote file S:\\tools\buffer.sql
1 create or replace trigger tt
2 before update on t for each row
3 begin
4 insert into t_log values (:old.key, :old.value);
5* end;
SYSTEM#dwal> /
Trigger created.
SYSTEM#dwal> update t set value = '123';
2 rows updated.
SYSTEM#dwal> commit;
Commit complete.
SYSTEM#dwal> select * from t_log;
KEY VALUE
---------- ----------
1 abcdef
2 ghijkl
SYSTEM#dwal> select * from t;
KEY VALUE
---------- ----------
1 123
2 123