Bind variable in SQL Developer with Oracle 11g - oracle

I have problem when trying to excute a sequence with a before insert trigger.
CREATE TABLE personne (ID number, nom varchar2(250 char));
CREATE SEQUENCE s_inc_pers START WITH 1 INCREMENT BY 1;
CREATE TRIGGER tr_inc_pers ON t1 BEFORE INSERT
FOR EACH ROW
DECLARE
BEGIN
select s_inc_pers into :new.t1.ID from DUAL;
END.

Oracle reports a bad bind variable if you try to reference something with :NEW that is not a column in the target table. In this case it may be prompting you for a bind value as the statement is malformed.
The NEW pseudorecord refers to the row in the triggering table that is being affected by the statement. You don't need to (and mustn't) include the table name when you use the pseudorecord field, so :new.t1.ID should just be :new.ID.
To get the next value from the sequence you need to use nextval, you can't only provide the sequence name.
Your clauses are also in the wrong order, you need the DML event (insert) befroe the target table.
CREATE TRIGGER tr_inc_pers BEFORE INSERT ON t1
FOR EACH ROW
BEGIN
select s_inc_pers.nextval into :new.ID from DUAL;
END;
As you are using 11g you don't even need to select from dual, you can just assign the column value:
CREATE TRIGGER tr_inc_pers BEFORE INSERT ON t1
FOR EACH ROW
BEGIN
:new.ID := s_inc_pers.nextval;
END;

Related

Oracle update trigger on the same table

I want to update field data_aktualizacji when some row in the same table is updated. I created the following compound trigger.
CREATE OR REPLACE TRIGGER oferta_update_trigger
FOR UPDATE ON oferty
compound TRIGGER
id_oferty number(10);
AFTER EACH ROW IS
BEGIN
id_oferty := :new.idk;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
UPDATE oferty SET data_aktualizacji = SYSDATE WHERE idk = id_oferty;
END AFTER STATEMENT;
END;
/
When I want to update some record, I get the following error.
SQL Error: ORA-00036: maximum number of recursive SQL levels (50) exceeded.
How to solve this problem? I this that some loop is created, but I don't know, how to workaround this.
Update oracle to alter the column to default to sysdate
Alter table oferty alter column data_aktualizacji set default sysdate
No need for trigger at all
As Ctznkane525 wrote, you definitively should use default-value to perform this action.
If you don't want to use default you can modify new.data_aktualizacji:
CREATE OR REPLACE TRIGGER oferty_update_aktualizacji
BEFORE INSERT OR UPDATE
ON oferty
FOR EACH ROW
DECLARE
BEGIN
:new.data_aktualizacji:= sysdate;
END;

Addition of values in two columns isn't working in PL/SQL ORACLE

So I am trying to add age with price and store the result on another table with the ID of the person who did this. I am able to set the business rule by making the trigger but when I check my second (END) table, there is nothing there.. Here is my code for the trigger:
CREATE OR REPLACE TRIGGER JIM
BEFORE INSERT ON END
FOR EACH ROW ENABLE
DECLARE
V_AGE JIM.AGE%TYPE;
V_PRICE JIM.PRICE%TYPE;
v_prices NUMBER(20);
BEGIN
SELECT AGE,PRICE INTO V_AGE,V_PRICE FROM JIM WHERE ID=:NEW.ID;
v_prices:=V_AGE+V_PRICE;
INSERT INTO END VALUES(:new.ID,v_prices);
END;
However, When I insert values onto the JIM table using the following code:
insert into jim values(4,'Sim',45,100);
nothing actually gets stored on the END table. i am sort of new to triggers and its so confusing. Please let me know what to do. thanls
Don't use a keyword end as a table name, this causes problem during
creation of trigger. I've presumed the table's name as t_end.
I think you are confused on which table to define trigger. It seems
you should define on table jim instead of t_end.
I've presumed you have a sequence named seq_end to populate the id
column of the table t_end
So , your trigger creation statement will be as follows :
create or replace trigger trg_ins_jim before insert on jim for each row
declare
v_id_end t_end.id%type;
v_prices t_end.prices%type;
begin
v_prices := :new.age + :new.price;
v_id_end := seq_end.nextval; insert into t_end values(v_id_end, v_prices);
/* if you have defined sequence for t_end as default value of id column, you may change the upper row as "insert into t_end(prices) values(v_prices);" and there would be no need for "v_id_end" */
end;
and when you issue insert into jim values(4,'Sim',45,100); command, you'll also have values inserted into t_end.
If there is only one table, then the SELECT and the INSERT are redundant.
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
:NEW.PRICES := :NEW.AGE + :NEW.PRICE;
END;
Possible duplicate

Get the inserted row via trigger Oracle

I have a trigger that gets a sequence number to put into my id column when insert a Row, the question is, how easily retun the new inserted row as resultSet.
create or replace trigger trg_Dependencia_id
before insert on DEPENDENCIA
for each row
begin
select DEPENDENCIA_id_seq.nextval
into :new.id
from dual;
end;
In Oracle, Triggers does not return any value. Also, triggers are not for this issues.
Maybe, you can insert your nextval a temp table after insert your table(DEPENDENCIA.DEPENDENCIA_id). Then you can handle it with a function.

Using INSERT INTO... SELECT in TRIGGER

The question I am going to ask is already there. But I don't have answer for this.
Please refer the below link.
ORACLE TRIGGER INSERT INTO ... (SELECT * ...)
I have around 600 columns in a table. After each insert in this table I need to insert the new row in another backup table.
Please tell how to use "INSERT INTO TABLE_NAME2 SELECT * FROM TABLE_NAME1" query in trigger.
Note: Without specifying columns in insert or select clause
Structure of both table is same. Specifying all the column name in trigger is difficult and also if new columns added, we need to add in trigger as well.
SQL> CREATE or REPLACE TRIGGER emp_after_insert AFTER INSERT ON emp
FOR EACH ROW
DECLARE
BEGIN
insert into emp_backup values (:new.empid, :new.fname, :new.lname);
DBMS_OUTPUT.PUT_LINE('Record successfully inserted into emp_backup table');
END;
reference:
http://www.tech-recipes.com/rx/19839/oracle-using-the-after-insert-and-after-update-triggers/
You should use COMPOUND TRIGGER. This trigger should look like this:
CREATE OR REPLACE TRIGGER t_copy_table1
FOR INSERT ON table1
COMPOUND TRIGGER
v_id number;
BEFORE EACH ROW IS
BEGIN
v_id := :new.id;
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
insert into table2 select * from table1 where id=v_id;
END AFTER STATEMENT;
END t_copy_table1;

Create trigger to insert into another table

I have some problem executing the trigger below:
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varReadNo Int;
varMeterID Int;
varCustID Varchar(10);
BEGIN
SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL;
Select MeterID INTO varMeterID
From Reading
Where ReadNo = varReadNo;
Select CustID INTO varCustID
From Address A
Join Meter M
on A.postCode = M.postCode
Where M.MeterID = varMeterID;
INSERT INTO BILL VALUES
(SEQBILLNO.NEXTVAL, SYSDATE, 'UNPAID' , 100 , varCustID , SEQREADNO.CURRVAL);
END;
Error Message:
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
Does it mean that I am not suppose to retrieve any details from table Reading?
I believe that the issue occur as I retrieving data from Table Reading while it is inserting the value:
SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL;
Select MeterID INTO varMeterID
From Reading
Where ReadNo = varReadNo;
It's there anyway to resolve this? Or is there a better method to do this? I need to insert a new row into table BILL after entering the table Reading where the ReadNo need to reference to the ReadNo I just insert.
You cannot retrieve records from the same table in a row trigger. You can access values from actual record using :new and :old (is this your case?). The trigger could then be rewritten to
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varCustID Varchar(10);
BEGIN
Select CustID INTO varCustID
From Address A
Join Meter M
on A.postCode = M.postCode
Where M.MeterID = :new.MeterID;
INSERT INTO BILL VALUES
(SEQBILLNO.NEXTVAL, SYSDATE, 'UNPAID' , 100 , varCustID , SEQREADNO.CURRVAL);
END;
If you need to query other record from READING table you have to use a combination of statement triggers, row trigger and a PLSQL collection. Good example of this is on AskTom.oracle.com
Make sure that you have the necessary permissions on all the tables and access to the sequences you're using in the insert.
I haven't done Oracle in awhile, but you can also try querying dba_errors (or all_errors) in order to try and get more information on why your SP isn't compiling.
Something to the tune of:
SELECT * FROM dba_errors WHERE owner = 'THEOWNER_OF_YOUR_SP';
Add exception handling in your trigger and see what is happening, by doing it would be easy for you to track the exceptions.
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varCustID Varchar(10);
BEGIN
-- your code
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20299)));
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20298)));
END;
we can combined insert and select statement
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varCustID Varchar(10);
BEGIN
insert into bill
values
select SEQBILLNO.NEXTVAL,
SYSDATE,
'UNPAID' ,
100 ,
CustID,SEQREADNO.CURRVAL
From Address A
Join Meter M
on A.postCode = M.postCode
Where M.MeterID = :new.MeterID;
END;
try the above code.

Resources