How to write trigger on the source table - plsql

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
);

Related

How do I reset a sequence in Oracle APEX or fill my PK automatically without sequence and trigger, starting from number 1 every time i delete my data?

i have this table
TABLE "KEYWORD_RSLT"
( "ID" NUMBER PRIMARY KEY,
"SESSION_MONTH" VARCHAR2(40) NOT NULL ENABLE,
"PATIENT_NAME" VARCHAR2(50)
and i have this procedure that imports data to my table KEYWORD_RSLT.
create or replace PROCEDURE "PR_KEYWORD_SEARCH" (v_patient_id NUMBER, v_keyWord varchar2)
IS
BEGIN
delete from KEYWORD_RSLT;
insert into KEYWORD_RSLT (SESSION_MONTH, PATIENT_NAME)
select distinct
to_char(s.SESSION_DATE, 'MM-YYYY') as SESSION_MONTH,
p.FIRST_NAME ||' '||p.LAST_NAME as PATIENT_NAME
from SESSIONS s,
CLIENTS p
where s.CLIENTS_ID = p.ID
and (s.CRITICAL_POINT like LOWER ('%'||v_keyWord||'%') and s.CLIENTS_ID = v_patient_id
or s.ACTIONS like LOWER ('%'||v_keyWord||'%') and s.CLIENTS_ID = v_patient_id);
END PR_KEYWORD_SEARCH;
I want my primary key "ID" to take automatically the next available number starting from 1, but when my procedure deletes all data from this table, i want to start again from 1.
I tried with sequence ("SQ_KEYWORD_RSLT_INCREAMENT") and trigger but i can not reset this sequence from a new procedure using this code:
alter sequence SQ_KEYWORD_RSLT_INCREAMENT restart start with 1;
How can i fill my ID automatically from the beginning every time i delete all the data?
You say i can not reset this sequence but you don't say why so I'm assuming that you got an error. It is not possible to execute ddl statements in pl/sql directly, but it can be done using EXECUTE IMMEDIATE.
CREATE SEQUENCE koen_s START WITH 1;
Sequence KOEN_S created.
SELECT koen_s.NEXTVAL FROM DUAL;
NEXTVAL
----------
1
BEGIN
EXECUTE IMMEDIATE 'ALTER SEQUENCE koen_s RESTART START WITH 1';
END;
/
PL/SQL procedure successfully completed.
SELECT koen_s.NEXTVAL FROM DUAL;
NEXTVAL
----------
1

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.

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.

update and insert triggers in sqlite

I want to have riggers that set the last_modified column automatically each time a row in updated or inserted.
Lets say I have an ID that is unique to each row.
This is my query:
CREATE TRIGGER insert_trigger
AFTER INSERT ON TABLE_NAME
BEGIN
update TABLE_NAME set last_modified =strftime('%Y-%m-%d %H:%M:%S:%s','now', 'localtime') where id = old.id;
END;
After creating this trigger, when I try to insert I get the error:
no such column: old.id
I can understand why I get this error, but how can I create a proper trigger?
When inserting, there is no old row.
To get the ID of the new row, use NEW.id.

After Insert Update Trigger PL/SQL

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;

Resources