After Insert Update Trigger PL/SQL - plsql

I have a table as Student and there is a varchar type column as status. i need to set value to this status column after insert or update process on this table. i have tried to write a Trigger for this. but i cant use as :new.status. it gives Error: ORA-04084: cannot change NEW values for this trigger type. how could i do this?
My Code
create or replace
TRIGGER STUDENT_AIU_TRI
AFTER INSERT OR UPDATE ON STUDENT
FOR EACH ROW
DECLARE
v_status VARCHAR2(2);
BEGIN
v_status := '1';
select v_status into :NEW.status from dual;
END;

If you want to change the value in a column, you'd need to use a BEFORE INSER OR UPDATET trigger, not an AFTER INSERT OR UPDATE trigger. Why do you believe that you need to use an AFTER INSERT OR UPDATE trigger?
You also don't need the local variable or to SELECT from dual
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT OR UPDATE ON student
FOR EACH ROW
BEGIN
:new.status := '1';
END;

Related

How to write trigger on the source table

I have a table data_package_code with schema as follows:
Name Null? Type
----------------- ----- ------------
mult qty VARCHAR2(2)
CHARGE NUMBER(19,4)
Credit Charge NUMBER(19,4)
Stop Date VARCHAR2(7)
Table_id NUMBER
SYS_CREATION_DATE DATE
I want to implement a trigger which will run an insert statement on the same table to add sysdate in sys_creation_date column.
It is done to store the date on which a new entry is inserted in the table.
My implementation is as follows:
create or replace trigger package_insert_date
before insert on data_package_code for each row
begin
insert into data_package_code(sys_creation_date)
values(sysdate);
end;
But it is giving me an error on line 2.
I am using oracle sql developer for this project.
It is just
create or replace trigger package_insert_date
before insert on data_package_code
for each row
begin
:new.sys_creation_date := sysdate;
end;
Although, you could have created table that way:
create table ...
(...
sys_creation_date date default sysdate --> this
);

PL/SQL not functioning

Im currently trying to implement a row trigger that fires when the new Employee number inserted into the table is not continuous.
"Continuous" in a relationship to the Employee number means the first record inserted will have the Employee number 1, the second record will have the employee number 2, and each next position must have a number greater by one that a number of the previous position.
I have successfully created the trigger, however when I inserted a new record that have an Employee number that is not continuous, my trigger is not fired.
Im unsure where I went wrong and hope I can get some explanation and corrections on my code.
CREATE OR REPLACE TRIGGER CONTENUM
AFTER INSERT ON TRKEMPLOYEE
FOR EACH ROW
DECLARE
continuous_value EXCEPTION;
PRAGMA exception_init(continuous_value, -20111);
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
IF (:NEW.E# > :OLD.E# + 1) THEN
RAISE_APPLICATION_ERROR (-20111,'The value of Employee number must be continuous');
END IF;
END CONTENUM;
/
Here is the format of my sample TRKEMPLOYEE table
CREATE TABLE TRKEMPLOYEE(
E# NUMBER(12) NOT NULL,
NAME VARCHAR(50) NOT NULL,
DOB DATE ,
ADDRESS VARCHAR(300) NOT NULL,
HIREDATE DATE NOT NULL,
CONSTRAINT TRKEMPLOYEE_PKEY PRIMARY KEY(E#) );
Here is my insert statement.
Currently in my table TRKEMPLOYEE there is only 15 rows thus with my insert statement, the trigger should fire but it is not happening.
INSERT INTO TRKEMPLOYEE VALUES( 17, 'David', NULL, 'GB',sysdate );
Thank you.
First of all you are checking AFTER INSERT ON TRKEMPLOYEE which will be executed after the row is inserted.
Secondly, you cannot check :OLD.E# since you are not updating and you are not using a old value.
Also you should drop the trigger at all and use SEQUENCES and let Oracle take care of the auto-increment values every time you add a new employee.
If you want to continue with your current logic, fixes that can be applied:
Change AFTER INSERT ON TRKEMPLOYEE to BEFORE INSERT ON TRKEMPLOYEE
Logic should be changed as below:
CREATE OR REPLACE TRIGGER contenum BEFORE
INSERT ON trkemployee
FOR EACH ROW
DECLARE
continuous_value EXCEPTION;
PRAGMA exception_init ( continuous_value, -20111 );
PRAGMA autonomous_transaction;
max_e# INTEGER;
BEGIN
SELECT
nvl(MAX(e#), 0)
INTO max_e#
FROM
trkemployee;
IF ( :new.e# > max_e# + 1 ) THEN
raise_application_error(-20111, 'The value of Employee number must be continuous');
END IF;
END contenum;
/
I do not recommend this solution because it will start to become slower as your table starts to grow.

ORA-00969: missing ON keyword 00969. 00000 - "missing ON keyword"

I am getting 0099 error while creating below trigger:
create trigger AuditTrigger1
before update, insert
on MPUZNTAB
for each row
declare
begin
insert into AuditTable1
(ZNCODE, DES , SHDES, WhenChanged)
values
(:new.ZNCODE,:new.DES,:new.SHDES, getdate())
end;
Please recomment changes
You missed a semicolon at the end of the insert statement
You should write before update OR insert
If getdate() is not a user defined function, you should use SYSDATE instead, to get the current time
I'm not sure the :new values are correct. Are they fields of the table MPUZNTAB?
This code should work:
Create Or Replace Trigger AuditTrigger1
Before Update Or Insert On MPUZNTAB
For Each Row
Declare
Begin
Insert Into AuditTable1
(ZNCODE,
DES,
SHDES,
WhenChanged)
Values
(:new.ZNCODE,
:new.DES,
:new.SHDES,
SYSDATE);
End;

How to use a bind variable in trigger body?

I'm new to PL/SQL. I'm using oracle 11g XE along with sql developer. I'm trying to create to create an after insert trigger as follows
create or replace trigger tr1
after
insert ON
employee
for each row
begin
print :new.emp_id;
end;
The employee table is as follows
create table employee
( emp_id varchar2(5) primary key,
emp_name varchar2(10),
salary number,
company varchar2(10) foreign key references companies(comp_name)
);
When I run the statement I got a 'enter binds' window for the bind variable :new. But I was confused that why do I need to enter the value for :new since it is pseudorecord. Then I entered 'employee' as the values for :new. Now I'm getting the following error.
Error(2,8): PLS-00103: Encountered the symbol "" when expecting one of the following: := . ( # % ; The symbol ":=" was substituted for "" to continue.
Your problem is not in the :new pseudorecord. The error is coming from the usage of print, which is used to print the bind variable used in successful PL/SQL block or used in an EXECUTE command. For example, you can use it this way:
VARIABLE n NUMBER
BEGIN
:n := 1;
END;
/
Then
PRINT n;
But if you want to test the value being inserted, you can use DBMS_OUTPUT.PUT_LINE like this:
create or replace trigger tr1
after
insert ON
employee
for each row
BEGIN
dbms_output.put_line(:new.emp_id);
END;
/
Enable DBMS_OUTPUT window in your SQL Developer, then run
insert into employee values(1, 'empName', 1000, 'ABC');
You'll see 1 printed out.
However, you can always test the value from the table. Because the value should be already inserted into table. You can just query.

how to use Trunc(mydate) in a cursor loop

I am new to PL/SQL, and am working on cursor today and got a scenario where I need to get the duplicate transaction type based on the date+amount+cust_id+txn_tpye. Once I get the duplicates I have to use another cursor or just normal loop using the select columns values (date+amount+cust_id+txn_tpye) as a where clause.
Before that I'm just trying to print them if I am getting a value or not, when I tried to print a mydate value getting error. Requesting help from you folks.
SET SERVEROUTPUT ON
declare
CURSOR dup_check
IS
SELECT cust_id,amount,trunc(mydate),transaction_type,COUNT(1)
FROM table_X WHERE trunc(mydate)>='10-OCT-2015'
GROUP BY cust_id,amount,trunc(mydate),transaction_type
HAVING COUNT(1)>1 ;
BEGIN
FOR UP_REC IN dup_check
LOOP
DBMS_OUTPUT.put_line(UP_REC.cust_id||' '||UP_REC.amount||UP_REC.trnasaction_type||**trunc(mydate))**;
END LOOP;
END;
**PLS-00302: component 'mydate' must be declared**
add alias for trunc(mydate) field as below and put the UP_REC.mydate in your dbms_output
SET SERVEROUTPUT ON
declare
CURSOR dup_check
IS
SELECT cust_id,
amount,
trunc(mydate) mydate, /* add an alias here */
transaction_type,
COUNT(1)
FROM table_X WHERE trunc(mydate) >= '10-OCT-2015'
GROUP BY cust_id,amount,trunc(mydate),transaction_type HAVING COUNT(1)>1 ;
BEGIN
FOR UP_REC IN dup_check
LOOP
DBMS_OUTPUT.put_line(UP_REC.cust_id||' '||UP_REC.amount||UP_REC.trnasaction_type||UP_REC.mydate));
END LOOP;
END;

Resources