¿Trigger in oracle after insert? - oracle

I have a netbeans web application using oracle database 11g, and i need to insert data on my table_B automatically after instert on my table_A,
my table_A has:
id_product
del_product
contrat
pre_prod
and my table_B has the same columns but i need to copy all data from table_A after update.
i'm new using triggeres and i don't know anythoing about it, Could you help me?
this the code i try but it doesn't work.
create or replace trigger color_omes
after update update of (id_del, dele, contr)
on dele
for each row
begin
insert into del3 values(new.id_del, new.dele, new.contr);
end color_omes;
but something went wrong, i get this error
ORA-00969: missing ON keyword

You have some issues in your code:
CREATE OR REPLACE TRIGGER color_omes
AFTER UPDATE OF id_del, dele, contr
ON dele
FOR EACH ROW
BEGIN
INSERT INTO del3 VALUES(:new.id_del, :new.dele, :new.contr);
END color_omes;
How it works:
SQL> select * from del3;
no rows selected
SQL> update dele set contr = 100;
1 row updated.
SQL> select * from del3;
ID_DEL DELE CONTR
---------- ---------- ----------
1 2 100

Related

adding a sequence to an existing table

i created a table but i forgot to add a sequence to one of the PK, its a sequence on a form page, i just cant find anything about it, is it possible or do i have to do the form all over again.
i tried to replace the PK but it doesnt give me the option to add the sequence when creating a new one.
i searched everywhere and asked the support in chat (didn't really help since its not their job).
all i could find was this and this.
I'd suggest you to skip Apex in this matter and do the following: presume this is your table:
SQL> create table test
2 (id number constraint pk_test primary key,
3 name varchar2(20)
4 );
Table created.
This is the sequence:
SQL> create sequence myseq;
Sequence created.
As you forgot to specify PK source while creating Apex Form page, never mind - let the database handle it. How? Create a BEFORE INSERT trigger:
SQL> create or replace trigger trg_bi_test
2 before insert on test
3 for each row
4 when (new.id is null)
5 begin
6 :new.id := myseq.nextval;
7 end trg_bi_test;
8 /
Trigger created.
Let's test it: I'm inserting only the NAME (which is what your Apex Form will be doing):
SQL> insert into test (name) values ('Littlefoot');
1 row created.
What is table's contents?
SQL> select * from test;
ID NAME
---------- --------------------
1 Littlefoot
SQL>
See? Trigger automatically inserted ID (primary key) column value.
If it were an Interactive Grid (which lets you insert several records at a time):
SQL> insert into test (name)
2 select 'Bigfoot' from dual union all
3 select 'FAD' from dual;
2 rows created.
SQL> select * from test;
ID NAME
---------- --------------------
1 Littlefoot
2 Bigfoot
3 FAD
SQL>
Works just fine.
And what's another benefit: you don't have to modify Apex application at all.

REFERENCING NEW TABLE AS is throwing invalid references in sql

Consider a view branch_cust defined as follows:
Create view branch_cust as
select
branch_name,
customer_name
from depositor, account
where depositor.account_number = account.account_number
suppose that a view is materialized; that is the view is computed and stored. Write a trigger to maintain the view, that is, to keep it up-to-date on insertions to and deletions from depositor or account. Do not bother about updates.
I tried doing an insert trigger on depositor using referencing new table as
But it is throwing errors.
This is the code.
create or replace trigger insert_dep
after insert on depositor REFERENCING NEW TABLE as inserted
FOR EACH ROW BEGIN
insert into branch_cust select branchname, cusname
from inserted, account
where inserted.account = account.acc; end;
Question is not clear, is branch_cust a table or view or materialized view ??
I will try to answer for all 3 cases :
branch_cust is view : and looking at the given DDL by you its a complex view, which means DMLs on it will fail. Also, since you are inserting into branch_cust(which is formed from table depositor) using a trigger which is also upon depositor you will get mutating error even if you make the view Simple.
so, this scenario will never work out.
branch_cust is materialized view : you cannot perform insert into a materialized view. so, trigger will fail
branch_cust is table : this can be achieved if you want to keep a separate copy of depositor data joined by account. but i suggest not to do it.
suppose that a view is materialized
Then it makes no sense in inserting into it, as those changes would be lost anyway at the first refresh.
Therefore, as it seems that you wanted to refresh it as soon as changes are made in its source table, set it to refresh on commit. Here's an example:
SQL> create materialized view mv_emp
2 refresh complete
3 on commit
4 as
5 select deptno, sum(sal) sumsal
6 From emp
7 group by deptno;
Materialized view created.
SQL> select * from mv_emp order by deptno;
DEPTNO SUMSAL
---------- ----------
10 13750
20 10995
30 9400
SQL> update emp set sal = sal + 1 where deptno = 10;
3 rows updated.
SQL> commit;
Commit complete.
SQL> select * from mv_emp order by deptno;
DEPTNO SUMSAL
---------- ----------
10 13753 --> new value for DEPTNO = 10
20 10995
30 9400
SQL>

Incorrect output while using dictionary tables inside Trigger

I am using ALL_TABLES/ALL_TAB_COLUMNS to get count of tables in my schema (EDW_SRC) and another schema(EDW_STG). I get correct counts when i run the query in my sql developer as shown below. But if i put the same query inside a trigger, i get wrong count for other schema(EDW_STG).
Please refer below code:
(This is just a sample code to replicate the issue, not my business requirement. I am referring ALL_TAB_COLUMNS in my actual code to get the number of columns in a particular table in different schema, for which i have Select access.)
select user from dual;
USER
-----
EDW_SRC
DROP TABLE ABC;
Table ABC dropped.
CREATE TABLE ABC(ID NUMBER);
Table ABC created.
select count(1) EDW_STG_CNT
from all_tables
where owner='EDW_STG';--Different Schema
EDW_STG_CNT
----------
101
select count(1) EDW_SRC_CNT
from all_tables
where owner='EDW_SRC';--My Schema
EDW_SRC_CNT
------------
1554
create or replace trigger trig_test_dml_abc
before insert on abc
DECLARE
V_STG_CNT number :=NULL;
V_SRC_CNT number :=NULL;
begin
DBMS_OUTPUT.PUT_LINE('***** TRIGGER OUTPUT *****');
select count(1) into V_SRC_CNT from all_tables
where owner='EDW_SRC'; --My Schema
DBMS_OUTPUT.PUT_LINE('My Schema EDW_SRC_CNT :'||V_SRC_CNT);
select count(1) into V_STG_CNT from all_tables
where owner='EDW_STG'; --Different Schema
DBMS_OUTPUT.PUT_LINE('Different Schema EDW_STG_CNT :'||V_STG_CNT);
end;
Trigger TRIG_TEST_DML_ABC compiled
INSERT INTO ABC VALUES (2);
1 row inserted.
***** TRIGGER OUTPUT *****
My Schema EDW_SRC_CNT :1554
Different Schema EDW_STG_CNT :2
The Different Schema count should be 101. Why is it coming as 2.
Oracle Version:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
Thanks
K

Update same table after Insert trigger

I am working on a product in which I have to send SMS to concerned person when someone waits for more than 15 minutes for being served.
For that I have written a procedure that watches a table and stores CUST_ID, CUST_CATEGORY, DURATION in a separate table when the Duration exceeds 15. The table structure of this table is:
Some_Table
CUST_ID CUST_CATEGORY DURATION SMS_STATUS
I wrote a trigger as:
Trigger
create or replace trigger kiosk_sms_trg
after insert on Some_Table
referencing new as new old as old
for each row
BEGIN
SMS_Proc#My_Server; --Procudure that generates SMS
update Some_Table set status = 'Y' where id = (select max(id) id from Some_Table where status = 'N'); --Update Table that SMS has been sent
select 'Y' into :new.status from dual;
END;
But it creates Mutation Problem. How do I resolve it? Any help would be highly appreciated. I'm using Oracle 11G.
I don't think that UPDATE is allowed on SOME_TABLE as it is currently mutating.
Why not place it right after the INSERT statement which fired the trigger in the first place?.
INSERT INTO SOME_TABLE ...
update Some_Table set status = 'Y' where id = (select max(id) id from Some_Table where status = 'N'); --Update Table that SMS has been sent
I guess this would be the right approach considering you aren't doing anything row specific in that UPDATE.
As I mentioned in the comment, Is there any particular use for this last statement in the AFTER INSERT trigger? It does have meaning in the BEFORE INSERT trigger.
select 'Y' into :new.status from dual;
You cannot update the same table in Row-Level AFTER Trigger.
Change your Row-Level AFTER INSERT trigger to row-level BFEORE INSERT trigger.
But you UPDATE stmt inside the trigger will not effect the new record being inserted.
Wonder how it can be done, this is tricky.

Oracle SEQUENCE.Currval problem in CodeIgniter

I have a sequence named WCOMP_SEQ in oracle to generate auto increment column ON WCOMP table. When I insert a row to WCOMP table in SQLPlus, the row inserted and I can get the auto increment value using
SELECT WCOMP_SEQ.currval FROM dual
But when I ran insert a row using Database Class in CodeIgniter, the row inserted but when I ran the query above to get auto increment value I got Exception:
Exception: Undefined Index currval in E:...
How to fix this?
There is a way to get the value automatically assigned to a column: it is the RETURNING clause.
So, here is my sequence:
SQL> select emp_seq.currval from dual
2 /
CURRVAL
----------
8140
SQL>
I'm going to use it in an INSERT statement:
SQL> var seqval number
SQL> insert into emp
2 (empno, ename, deptno, sal, job)
3 values
4 (emp_seq.nextval, 'JELLEMA', 50, 4575, 'PAINTER')
5 returning empno into :seqval
6 /
1 row created.
SQL>
I returned the EMPNO into a SQL*Plus variable which I can print, and it has the same value as CURRVAL:
SQL> print :seqval
SEQVAL
----------
8141
SQL> select emp_seq.currval from dual
2 /
CURRVAL
----------
8141
SQL>
Your next question is, "does CodeIgniter support the RETURNING sysntax?" I have no idea, but I suspect it does not. Most non-Oracle frameworks don't.
There is always the option to wrap the INSERT statement in a stored procedure, but that's an architectural decision whoch many people dislike.
You can not fetch the SEQUENCE current value without issuing NEXTVAL (see here). So, if you do not want to increment the sequence value (by using NEXTVAL), you should instead query USER_SEQUENCES.
Something like this:
select Sequence_Name
, Last_Number
from user_sequences
where sequence_name = 'WCOMP_SEQ'
/
SEQUENCE_NAME LAST_NUMBER
------------- -----------
WCOMP_SEQ 20
Hope this helps.
In order to get currval on the sequence you will need to have at least one reference to the corresponding nextval for the sequence in the current user session. This is what causes it to set the currval value which would belong to the session.
If you are using it outside, it defeats the purpose which value could it return if there were other sessions active.

Resources