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;
/
Related
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
I would like to create a ORACLE plsql trigger in my booking table which will prevent user to update value where booking start date like <= sysdate.
in my booking table booking start date column name is date_from. I have tried following command but seems like I am using wrong code.
create or replace TRIGGER UPDATE_BOOKING
BEFORE UPDATE ON BOOKING
FOR EACH ROW
BEGIN
IF BOOKING.DATE_FROM <= TO_DATE(SYSDATE)
THEN
RAISE_APPLICATION_ERROR (-20001,'YOU CAN NOT UPDATE BOOKING STATUS WHERE ......');
END IF;
END;
what would be the best way to implement this trigger.
If you want to compare the existing value of the date then use :old. If you are updating the date column also and you want check it for the new value of update date then use :new. Example for :old is as follows..
create or replace TRIGGER UPDATE_BOOKING
BEFORE UPDATE ON BOOKING
FOR EACH ROW
BEGIN
IF :OLD.DATE_FROM <= TO_DATE(SYSDATE)
THEN
RAISE_APPLICATION_ERROR (-20001,'YOU CAN NOT UPDATE BOOKING STATUS WHERE ......');
END IF;
END;
No need to use to_date() function for sysdate, its already date type, check the following code:
create or replace TRIGGER UPDATE_BOOKING
BEFORE UPDATE ON BOOKING
FOR EACH ROW
BEGIN
-- used trunc function below for more accuracy
IF trunc(:OLD.DATE_FROM) <= trunc(SYSDATE)
THEN
RAISE_APPLICATION_ERROR (-20001,'YOU CAN NOT UPDATE BOOKING STATUS WHERE ......');
END IF;
END;
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;
I was tasked to create triggers to insert into a log table when an order table was
Inserted into
updated
also insert/delete/update was to be disabled between 5pm friday and 9am monday. The solution that follows covers all this, however because it is a before trigger I have had to turn off integrity constraints (does this matter for a log table?)
Does anyone have any suggestions how I might be able to do this AND keep the integrity constraints (on the logono column)?
I was thinking about 11G compunt triggers but it was sugegsted in a previous answer that this would not be an appropriate use, plus the issue with backwards compatibility.
CREATE OR REPLACE TRIGGER log_order
BEFORE INSERT OR UPDATE OR DELETE ON orders
FOR EACH ROW
DECLARE out_of_hours EXCEPTION;
BEGIN
IF INSERTING THEN
IF
TO_NUMBER( TO_CHAR( SYSDATE, 'DHH24' ) ) BETWEEN 109 AND 517 THEN
insert into order_log values
(order_log_PK.nextval,
(select user from dual),
:NEW.ono,
(select SYSDATE from dual),
'Order Inserted' ) ;
ELSE
RAISE out_of_hours;
END IF;
END IF;
IF UPDATING THEN
IF
TO_NUMBER( TO_CHAR( SYSDATE, 'DHH24' ) ) BETWEEN 109 AND 517 THEN
insert into order_log values
(order_log_PK.nextval,
(select user from dual),
:NEW.ono,
(select SYSDATE from dual),
'order updated' ) ;
ELSE
RAISE out_of_hours;
END IF;
END IF;
IF DELETING THEN
IF
TO_NUMBER( TO_CHAR( SYSDATE, 'DHH24' ) ) BETWEEN 109 AND 517
THEN
RAISE out_of_hourS;
END IF;
END IF;
EXCEPTION
WHEN out_of_hours THEN
dbms_output.put_line('there is not privelages at this time');
RAISE_APPLICATION_ERROR(-20001, 'CANNOT UPDATE OUT OF HOURS');
END;
thanks
EDIT
The integrity issue came about becaue the :NEW.ono value going into the Log Table is not yet inserted into the order table due to this being a before trigger, therefore violating the logono Foreign Key.
You can simplify your trigger so that you only check the Monday 9am - Friday 5pm condition once, so that you only have one place where you insert into the log table, and to eliminate the need for an extra exception and an exception handler.
You can make the trigger an AFTER INSERT trigger so that the trigger executes after the data already exists in ORDERS so that you could create a foreign key constraint in ORDER_LOG that references the ONO key in ORDERS. However, it would seem very odd to want to create that sort of constraint. If you create your log table as a child of the base table, that would mean that you either would never be able to delete a row from ORDERS, since there would always be a child row, or that you would need to delete all the rows from ORDER_LOG for that ONO before doing the delete. Neither of those is generally particularly desirable-- in general, the point of having a log table is that it will log all the operations, not just the operations on rows in the base table that are still present.
CREATE OR REPLACE TRIGGER log_order
AFTER INSERT OR UPDATE OR DELETE ON orders
FOR EACH ROW
DECLARE
l_operation varchar2(30);
BEGIN
if to_number( to_char( sysdate, 'ddhh24' ) ) between 109 and 517
then
if inserting
then
l_operation := 'Order inserted';
elsif updating
then
l_operation := 'Order updated';
end if;
-- Note that I'm guessing at the names of the columns in order_log
insert into order_log( order_log_pk,
modify_user,
ono,
modify_date,
description )
values( order_log_PK.nextval,
user,
:new.ono,
sysdate,
l_operation );
else
raise_application_error( -20001, 'Cannot update out of hours' );
end if;
END;
While it may be syntactically valid to do an INSERT into a table without listing the columns you are inserting into, doing so is dangerous. If you add another column in the future, even if it is not required, your INSERT will start failing. If you list the columns explicitly, the trigger will continue to work. It is also relatively hard to spot bugs where data is being inserted into the wrong column if you don't list the columns explicitly. I guessed at what the columns were-- you'll have to substitute the proper column names.
I'm very new for trigger, now this what i was trying. I've two tables INSERTED and ORDER_INFO, both have the same column name ORDER_ID, ORDER_DATE. I've scenario, where client will be placing his/her order then, order information will be stored into INSERTED table, then by using this trigger, it'll insert into another table ORDER_INFO after satisfying the condition, which has been written.
create trigger tri_check
AFTER INSERT ON inserted FOR EACH ROW
DECLARE
v_date DATE;
BEGIN
SELECT order_date INTO v_date FROM inserted;
if (v_date)< (sysdate + 2) then
raiserror('You cannot take an order to be delivered less than 2 days from now',16, 1);
else
INSERT INTO orders_info
( order_id,order_date)
VALUES
(:new.order_id,v_date);
end if;
end;
But, when i'm executing the above trigger, then i'm getting this error.
ERROR at line 8: PL/SQL: SQL Statement ignored
6. SELECT order_date INTO v_date FROM inserted;
7. if (v_date)< (sysdate + 2) then
8. raiserror('You cannot take an order to be delivered less than 2 days from now',16, 1);
9. else
10. INSERT INTO orders_info
EDIT
Now, i made the same structure table into SYSTEM user, and got the same error. Table or View does not exist
Need help !! Thanks in advance !!
The message seems to indicate a problem with the 'raiserror' procedure. I'm not familiar with such a procedure in standard PL/SQL - did you mean RAISE_APPLICATION_ERROR? However, and perhaps more to the point, when using a trigger there's no need to do a SELECT from the table. All the data being inserted is available to the trigger. I suggest changing your trigger to be something like the following:
create trigger tri_check
AFTER INSERT ON inserted
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
if :new.ORDER_DATE < sysdate + INTERVAL '2' DAY then
RAISE_APPLICATION_ERROR(-20000, 'You cannot take an order to be delivered less than 2 days from now');
else
INSERT INTO orders_info
(order_id, order_date)
VALUES
(:new.order_id, :new.ORDER_DATE);
end if;
end TRI_CHECK;
Share and enjoy.
You can just use the :NEW and :OLD values instead of your select:
CREATE TRIGGER tri_check
AFTER INSERT
ON inserted
FOR EACH ROW
DECLARE
BEGIN
IF :new.order_date < (SYSDATE + 2)
THEN
raiserror (
'You cannot take an order to be delivered less than 2 days from now',
16,
1);
ELSE
INSERT INTO orders_info (order_id, order_date)
VALUES (:new.order_id, :new.order_date);
END IF;
END;
What is your raiserror procedure? Do you have access permissions granted on it?
Hope it helps...
EDIT:
OK, from your error, and the error you posted on #Bob Jarvis' answer, you might not have INSERT privilege on the ORDERS_INFO table. You also should check your permissions on the INSERTED table too.
Check your permissions with your DBA.
If raiserror is not a defined procedure or you don't have access to it then use the RAISE_APPLICATION_ERROR method for raising an error as Bob suggests.