oracle trigger query - oracle

I have a trigger which is sending data from a table to another table in another database. all s working fine.
The prob is that there is a new concept of END DATE, in which, if END DATE is present for a person, the row should reach the other table on that particular date..
eg.: if someones end date is 31st august, it should go on that day only, but ofcourse, my trigger is firing on event change (when enddate is set to 31st august)..
Could you please suggest me what I can do to SET the row to go on ENDDATE.?

It doesn't sound like you don't want a trigger. It sounds like you want a job. For example, if you create a procedure that transfers all the rows whose end_date is today
CREATE OR REPLACE PROCEDURE move_rows_with_end_date(
p_end_date IN DATE DEFAULT trunc(SYSDATE)
)
AS
BEGIN
INSERT INTO table_name#remote_database( <<list of columns>> )
SELECT <<list of columns>>
FROM table_name
WHERE end_date = trunc(sysdate);
END;
Then you can create a job that runs the procedure every day at midnight
DECLARE
l_jobno PLS_INTEGER;
BEGIN
dbms_job.submit( l_jobno,
'BEGIN move_rows_with_end_date; END;',
trunc(sysdate+1),
'trunc(sysdate+1)' );
commit;
END;

Related

How can we Create a Trigger(or any Object) to insert rows into Attendance table when a certain time of day passes?

I am new to PL/SQL and Oracle APEX. In oracle APEX, I'm trying to create a trigger that will fire when employees are not present after a certain time, say for example 12:00 PM and it's not friday.
I have these columns in the Attendances Table: emp_id, work_date, attend_stat.
The emp_id is a foreign key referenced from Employees Table
When it's past 12:00 PM, and there was no attendance entry for a particular employee, I want a row inserted for that employee like this:
insert into attendances(emp_id, work_date, attend_Stat)
values("ID OF NOT PRESENT EMPLOYEE", sysdate, 'A');
I have written this pl/sql statement but I cannot find a way to implement it or figure out will it even work.
declare
cursor c_emp_id is
select emp_id from employees;
cursor c_emp_at is
select emp_id from attendances where work_date = sysdate and to_char(sysdate,'DAY') <> 'FRIDAY';
begin
for i in c_emp_id loop
for a in c_emp_at loop
if i.emp_id <> a.emp_id then
insert into attendances(emp_id, work_date, attend_stat)
values(i.emp_id, systimestamp, 'A');
end if;
end loop;
end loop;
exception
when no_data_found then
for i in c_emp_id loop
insert into attendances(emp_id, work_date, attend_stat)
values(i.emp_id, systimestamp, 'A');
end loop;
end;
How can I achieve this?
You need to save the code in a package or in a stored procedure and set it to run as a database job. See the documentation for details.
Please note the doc is for version 11 of the database, check the version you are on
select version from v$instance
and google for actual docs

How to use Trigger with joining 2 tables?

I have 2 tables one is Schedule_table :
SID NOT NULL NUMBER(38)
FNUMBER VARCHAR2(20)
DEPARTURE_TIME TIMESTAMP(6) WITH TIME ZONE
ARRIVAL_TIME TIMESTAMP(6) WITH TIME ZONE
PRICE NUMBER
The second table is Flight_table
FNUMBER NOT NULL VARCHAR2(20)
DEPARTURE_APCODE CHAR(3)
ARRIVAL_APCODE CHAR(3)
Fnumber is PK in Flight_table and FK in Schedule_table.
I want the trigger to fire when the PRICE gets changed in Schedule_table
Also, to print a message of (Fnumber, ARRIVAL_APCODE, DEPARTURE_TIME ,ARRIVAL_APCODE).
I wrote this Code, it did not work.
create or replace trigger schedule_trigger after update on schedule
for each row when (new. price <> old. price)
begin
dbms_output.put_line( 'the flight number ' || :new.fnumber|| DEPARTURE_APCODE ||DEPARTURE_TIME|| ' has changed to '||:new.price ||' From'||:old.price);
end;
You are referring to the columns of Flight table - DEPARTURE_APCODE and DEPARTURE_TIME directly inside trigger which is not possible.You need to use a select
to fetch those values.
CREATE OR REPLACE TRIGGER schedule_trigger AFTER
UPDATE ON schedule
FOR EACH ROW
WHEN ( new.price <> old.price )
DECLARE
v_departure_apcode flight.departure_apcode%TYPE;
v_arrival_apcode flight.arrival_apcode%TYPE;
BEGIN
SELECT
departure_apcode,
arrival_apcode
INTO
v_departure_apcode,v_arrival_apcode
FROM
flight
WHERE
fnumber =:new.fnumber;
dbms_output.put_line('The flight number '
||:new.fnumber
|| v_departure_apcode
|| v_arrival_apcode
|| ' has changed to '
||:new.price
|| ' From '
||:old.price);
END;
/
And note that using DBMS_OUTPUT.PUT_LINE() inside a trigger is of no use as SQL developer sometimes does not display your output. Better create a log table and insert the records into it in your trigger.
You may require a commit statement for the output to be displayed.
SET SERVEROUTPUT ON;
UPDATE Schedule SET PRICE = 2502.00 where fnumber = 'F2004' ;
commit;
Commit complete.
The flight number F2004AB CD has changed to 2502 From 2501

create a trigger in oracle to avoid insertion on sunday

I have employee table in oracle.I want to create a trigger that will avoid insertion of data on sun day. please tell me the program?following program not working.
Here's an example trigger that checks for week day and, if day is sunday (7), throws an user defined exception ORA-20000:
CREATE OR REPLACE TRIGGER trg_sunday
BEFORE INSERT ON employee
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF TO_CHAR(SYSDATE, 'D') = '7' THEN
RAISE_APPLICATION_ERROR(-20000, 'Cannot insert record on sunday');
END IF;
END;
Please check which number identifies sunday, it depends on the local NLS settings of the database. Here in Italy (NLS_TERRITORY='ITALY') Sunday is identified by 7 but with different database NLS setting the number may vary.
You may take a look at Day of week (1-7) and NLS settings
The trigger remains the same but the query goes like below:
to check whats day today"
select to_char(to_date('08/08/2016','dd/mm/yyyy'), 'DY'),TO_CHAR(SYSDATE, 'D') from dual;
To check next sunday:
select to_char(to_date('14/08/2016','dd/mm/yyyy'), 'DY'),TO_CHAR(to_date('14/08/2016','dd/mm/yyyy'), 'D') from dual;
The correct code should be:
CREATE OR REPLACE TRIGGER trg_sunday
BEFORE INSERT ON employee
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF TO_CHAR(SYSDATE, 'D') = '1' THEN ---Should be 1 rather than 7
RAISE_APPLICATION_ERROR(-20000, 'Cannot insert record on sunday');
END IF;
END;
You can create your trigger as shown in below code snippet.
CREATE OR REPLACE TRIGGER sunday_prevent
BEFORE INSERT ON account
FOR EACH ROW
Begin
IF TO_CHAR(SYSDATE,'day')='sunday' then
raise_application_error(-20000,'Today is Sunday so you not perform any transaction');
END IF;
END;
/

Timestamp issue in oracle schedule jobs

I wrote a procedure to dump dba_audit_trail information to a flat file and once it done purge the sys.audit table. Execute the procedure manually it dump the data correctly to flat file. But it execute as a schedule job TIMESTAMP is not correct. TIMESTAMP is 6 hours less than TIMESTAMP in dba_audit_trail table.
Table content
------------------------
31-07-2014 07:26:08,EOMCBOFD,CFNET\CBOEDPS5,Administrator,CBOEDPS5,LOGON,,
31-07-2014 07:26:24,EOMCBOFD,CFNET\CBOEDPS5,Administrator,CBOEDPS5,LOGOFF BY CLEANUP,,
Flat file content
-------------------
31-07-2014 01:26:08,EOMCBOFD,CFNET\CBOEDPS5,Administrator,CBOEDPS5,LOGON,,
31-07-2014 01:26:24,EOMCBOFD,CFNET\CBOEDPS5,Administrator,CBOEDPS5,LOGOFF BY CLEANUP,,
CREATE OR REPLACE PROCEDURE SYS.ddl_audit_log_purge AS
CURSOR cur_date IS`enter code here`
SELECT sysdate FROM dual;
rec1 cur_date%ROWTYPE;
created_file_name VARCHAR2(100);
file_name UTL_FILE.FILE_TYPE;
BEGIN
OPEN cur_date;
LOOP
FETCH cur_date INTO rec1;
EXIT WHEN cur_date%NOTFOUND;
created_file_name:=rec1.sysdate;
file_name:=UTL_FILE.FOPEN('AUD_DIR','cfcbo_'||created_file_name||'.exp','W');
FOR rec in(
SELECT to_char(TIMESTAMP, 'dd-mm-yyyy HH24:MI:SS')
||','||username
||','||userhost
||','||os_username
||','||terminal
||','||action_name
||','||owner
||','||obj_name
out_line
FROM dba_audit_trail)
LOOP
UTL_FILE.PUTF(file_name,'%s\n',rec.out_line);
UTL_FILE.FFLUSH(file_name);
END LOOP;
UTL_FILE.FCLOSE(file_name);
END LOOP;
CLOSE cur_date;
insert into aud_log_job (now,task) values(sysdate,'exported audit table');
execute immediate 'truncate table sys.aud$';
insert into aud_log_job(now,task) values(sysdate,'truncate audit table');
END;
/
This is actually quite complicated issue. Check this Oracle support node:
DBMS_SCHEDULER or DBMS_JOB And DST / Timezones Explained (Doc ID 467722.1)
"The sysdate and systimestamp "seen" by jobs may be different then the one when you connect, the used timezone is the one that was set when the database (!) was started."

Character to number conversion error in trigger

How will the trigger insert between two timings? Getting character to number conversion error in the if condition while inserting. Below is my trigger.
create or replace trigger TRI_INSERT
after insert on stud_details
referencing old as old new as new
for each row
declare
strTime varchar2(20) := :new.time_stamp; -- (eg: '02/08/2013 11:09:42 PM')
begin
if (to_char(strTime, 'hh24:mi:ss') between '22:00:00' and '23:59:59') then
insert into stud_clas_details
(id,
v-id,
w-id,
al_id,
time,
Time_Stamp)
values
(seq_ve_id.nextval,
:new.vehicle_id,
:new.way_id,
'xxxx',
strTime,
sysdate);
end if;
end TRI_INSERT;
you cannot to_char() a varchar2 with a date format and expect it to work.
instead you should do
if (to_char(:new.time_stamp, 'hh24:mi:ss') between '22:00:00' and '23:59:59') then
also if you want to insert the time into the table in a specific format, use
to_char(:new.time_stamp, 'hh24:mi:ss')
as with
strTime varchar2(20) := :new.time_stamp;
you will just be inserting the date in whatever the default NLS_DATE_FORMAT is for that session (which may vary per session).
How about instead using:
if extract(hour from :new.time_stamp) in (22,23) then ...
Problem in the if condition.. Now its working fine.. Thanks for all.
create or replace trigger TRI_INSERT
after insert on stud_details
referencing old as old new as new
for each row
declare
strTime varchar2(20) := :new.time_stamp; -- (eg: '02/08/2013 11:09:42 PM')
strFromTime varchar2(20):= '22:00:00'
strToTime varchar2(20):= '23:59:59'
begin
if ((to_char(strTime, 'hh24:mi:ss') > strFromTime) and (to_char(strTime,
'hh24:mi:ss') < strToTime)) then
insert into stud_clas_details
(id,
v-id,
w-id,
al_id,
time,
Time_Stamp)
values
(seq_ve_id.nextval,
:new.vehicle_id,
:new.way_id,
'xxxx',
strTime,
sysdate);
end if;
end TRI_INSERT;

Resources