how to get value on other table in trigger on oracle - oracle

declare
tgl RENC_DITSEK.TGL_INPUT%TYPE;
thn varchar(10) := :new.tahun + 1;
target RENC_DITSEK.TARGET_2%TYPE;
BEGIN
select TARGET_2 into target from RENC_DITSEK where KODE_RENCANA = :NEW.KODE_RENCANA;
SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYY HH24:MI:SS') INTO tgl FROM DUAL;
IF UPDATING ('TARGET_2') THEN
INSERT INTO NOTE_LOG VALUES(:NEW.PKP,'',:NEW.INDIKATOR,'Target Tahun '||thn,'',:new.target_2,**target**,tgl,'','0');
END IF;
END;
hi, there is my trigger body. i need a value of TARGET_2 before it updated, but i have no ide to do that. so this is my code, but it error "mutating table". is there a way to do that? please help.
thanks for helping.

it would help if you provide the table and the trigger definitions.
e.g. what table are you creating the trigger on? Is KODE_RENCANA the primary key of the table?
If the answer to the above questions is Yes, then you don't need to execute a SELECT statement, since you could get the value of TARGET_2 using :OLD.TARGET_2 for the record you're updating.
If KODE_RENCANA is not the primary key, and it is actually a field that could be updated, and you want to retrieve another record in the same table given the new KODE_RENCANA value, then the problem is more complicated, which I would not recommend using a trigger to handle, instead, try creating a stored procedure and call the stored procedure to perform the update.
cheers.

Related

Oracle_Trigger: Auto Update Of a Column Based Upon INSERT/UPDATE

This might appear a simple query for most of you, but I am a beginner in Oracle DB.
A table has been created with below script-
CREATE TABLE PLAN_TABLE
(
PL_ID DECIMAL(10,0) PRIMARY KEY NOT NULL
,PL_NAME VARCHAR2(300) DEFAULT NULL
,UPDATED_TS TIMESTAMP DEFAULT SYSDATE NOT NULL
,DELETE_FLAG DECIMAL(10,0) DEFAULT 0 NOT NULL
);
The requirement is to have SYSDATE for UPDATED_TS for any new record inserted into the table and also in case when the DELETE_FLAG is updated to 1. Can it be done by trigger?
The below trigger was created-
CREATE OR REPLACE TRIGGER PT_BEFORE_INSERT_TR
BEFORE INSERT ON PLAN_TABLE
FOR EACH ROW
BEGIN
SELECT SYSDATE INTO :new.UPDATED_TS FROM DUAL;
dbms_output.put_line('Inserted');
END;
/
Below error was encountered while inserting record into the table-
error: ORA-04091: table I60_SCH04.PLAN_TABLE is mutating, trigger/function may not see it
Can you please help in letting me know that where am I committing the mistake? Is there any better way to achieve the requirement based upon INSERT/UPDATE?
The actual error you get is due to the fact that you try to select from a table that you actually are changing. To prevent the issue there are a couple of methods, but in you case things are really simple.
SYSDATE is a function, that you could call directly inside PL/SQL block (which a trigger actually is) and use the value returned to update the set the column value
CREATE OR REPLACE TRIGGER PT_BEFORE_INSERT_TR
BEFORE INSERT ON PLAN_TABLE
FOR EACH ROW
BEGIN
:new.UPDATED_TS := sysdate;
dbms_output.put_line('Inserted');
END;
/
OK, this covers the insert part.
For updating - once again, many options. One could be - change your trigger to BEFORE INSERT OR UPDATE ON PLAN_TABLE.
In this case whenever you issue update or insert - this trigger is fired for each row and updates the date column accordingly.
And of course you could use particular checks available in triggers, something like
IF INSERTING OR UPDATING('DELETE_FLAG') THEN
...
END IF;
and code in the logic you need.

Trigger in oracle SQL - Validation?

Hello guys I'm trying to create a trigger to validate some data, I've got a table called 'Events' and what I need to do create a trigger that will give me an error when you try to add an event in July.
CREATE OR REPLACE TRIGGER concert_trigger
AFTER INSERT ON CONCERT
WHEN (event_date = 'July')
BEGIN
ALTER TABLE CONCERT
ADD CONSTRAINT chk_CONCERT CHECK (event.date ='July')
END;
Here is the trigger that I have started that I think is the way to go but I'm not sure if this is right.
Thanks, Leprejohn
Since your classwork requires the use of a trigger you'd want to do something like
CREATE OR REPLACE TRIGGER CONCERT_BI
BEFORE INSERT ON CONCERT
FOR EACH ROW
BEGIN
IF TO_CHAR(EVENT_DATE, 'MON') = 'JUL' THEN
RAISE_APPLICATION_ERROR(-20666, 'No concerts can be scheduled in July');
END IF;
END CONCERT_BI;
Here I'm assuming that EVENT_DATE is an actual DATE instead of a character string; if that was a bad guess then change the comparison appropriately.

create trigger for copying values between tables in oracle

I am new to the sql. I want to create a trigger for copying values between tables.
basically, the task I want to finish is forwarding students' message table values to specific staff_maibox
here is the code.
drop trigger forward_msg_to_staff;
create or replace trigger forward_msg_to_staff
update on message
for each row
declare
message_id VARCHAR2(10);
client_id NUMBER(10);
staff_id NUMBER(5);
message_date DATE;
message_title VARCHAR2(20);
staff_mailbox VARCHAR2(255);
begin
insert into staff_mailbox(message_id, client_id, staff_id, message_date, message_title, staff_mailbox)
values(:new.message_id, :new.client_id, :new.staff_id, :sysdate, :new.message_title, :old.staff_mailbox)
end;
/
is this code correct?
Please advise. thanks in advance.
You're getting an error because you're missing either the BEFORE or AFTER keyword from the CREATE TRIGGER statement.
These are required as indicated in the documentation:
Additionally:
There's no need to declare all the variables, you're not using them
:sysdate is incorrect, you're not binding it. You can just use sysdate instead as you would in standard SQL or PL/SQL.
You're missing a semi-colon after the VALUES clause of the INSERT statement.
Putting this together your trigger may look like this
create or replace trigger forward_msg_to_staff
after update on message
for each row
begin
insert into staff_mailbox( message_id, client_id, staff_id, message_date
, message_title, staff_mailbox )
values ( :new.message_id, :new.client_id, :new.staff_id, sysdate
, :new.message_title, :old.staff_mailbox );
end forward_msg_to_staff;
/
Note that I've used the trigger name in the END as well. This is for convenience only, it makes it obvious where the trigger ends...
If you want to see what errors your're getting when you're creating a trigger use show errors as a_horse_with_no_name suggests. This shows any compilation errors, which is invaluable for tracking them down.

How to create Oracle Trigger to record current SQL

I am currently doing a homework assignment and am getting stuck at a point.
I want to create a trigger for auditing, and Yes I do know FGA, but that's not what was asked.
My trigger needs to record the current SQL for auditing. This is what I have now.
Imagine I have my table already created to store the inserting value.
CREATE OR REPLACE TRIGGER ALL_SQL_AUDIT
AFTER UPDATE ON SCOTT.EMP
FOR EACH ROW
BEGIN
INSERT INTO ALL_SQL_AUDIT(TABLE_NAME, SQL_TEXT, SQL_TYPE, CHANGE_DATE, DB_USERNAME, OS_USERNAME)
SELECT 'SCOTT.EMP',
SYS_CONTEXT('USERENV','CURRENT_SQL'),
'UPDATE',
SYSDATE,
USER,
SYS_CONTEXT('USERENV','OS_USER')
FROM dual;
END;
/
Problem is SYS_CONTEXT('USERENV','CURRENT_SQL') never return anything, so does anyone know how to get the current DML that triggered this event?

Store the data of deleted record using trigger

I want to write a trigger which fires on deletion of a record from a table, and inserts a record in another table and uses the details of the record deleted.
Database : Oracle 10g
My trigger looked like this
CREATE or REPLACE TRIGGER myTrigger
AFTER DELETE
ON myTable
REFERENCING NEW AS old_tab
FOR EACH ROW
BEGIN
INSERT INTO ACTIVITYLOG values ('ADMIN',:old_tab.tabletID,'MIGRATION','ERROR','TEST','T','NIL',sysdate)
END;
here :old_tab.tabletID the tabletID is the column of the table myTable in which deletion is done.
I want to save the I and a log that it was deleted.
But when I try deleting a record I get the following error
Error code 4098, SQL state 42000: ORA-04098: trigger 'DB.MYTRIGGER' is
invalid and failed re-validation
P.S. Ran the trigger creation in NetBeans SQL Editor.
Here is the,
EDIT
STRUCTURE OF myTable (Table deletion occurs)
tabletID varchar2(15) PRIMARY KEY
tabletName varchar2(100)
STRUCTURE OF ACTIVITYLOG
username varchar2(15)
tabletKey varchar2(15)
page_ref varchar2(100)
errors varchar2(100)
remarks varchar2(100)
operationcode char(2)
lastupdateip varchar2(20)
lastupdatedate date
Sorry don't have access to SQL PLUS EDITOR.
You should use the :OLD values rather than the :NEW values. The :NEW values in a DELETE trigger (whether BEFORE or AFTER) are blank. This makes sense, because if you think about it the record has logically ceased to exist at this point.
However that is not a source of compilation errors.
"still the same error shows up on deletion. "
I suppose we could spend all day guessing what's wrong so let's stop now. You can discover the compilation errors with this simple query:
select * from user_errors
where name = 'MYTRIGGER'
and type = 'TRIGGER'
"I changed the :NEW to :OLD, and added a semicolan and ran it on SQL
PLUS, and that did the trick"
For the benefit of future here is a version of the trigger which will compile and which will correctly write the required values:
CREATE or REPLACE TRIGGER myTrigger
AFTER DELETE
ON myTable
REFERENCING OLD AS old_tab
FOR EACH ROW
BEGIN
INSERT INTO ACTIVITYLOG values ('ADMIN',:old_tab.tabletID,'MIGRATION','ERROR','TEST','T','NIL',sysdate);
END;
/
The problem is this:
REFERENCING NEW AS old_tab
You've redefined the NEW values with the label "old_tab". This is somewhat like adding #define FALSE TRUE to the top of a program.
Add a semicolon after the insert statement
Because you're using an AFTER DELETE trigger, you only need to access the :OLD values, e.g.:
CREATE or REPLACE TRIGGER myTrigger
AFTER DELETE
ON myTable
FOR EACH ROW
BEGIN
INSERT INTO ACTIVITYLOG values ('ADMIN',:OLD.tabletID,'MIGRATION','ERROR','TEST','T','NIL',sysdate);
END;

Resources