Error while creating trigger on table in Oracle - oracle

I am creating a trigger for inserting incremental ID's in my table. But while creating I am getting below error
An error occurred while processing a recursive SQL statement
(a statement applying to internal dictionary tables).
ORA-00604: error occurred at recursive SQL level 1
ORA-01654: unable to extend index SYS.I_TRIGGERCOL1 by 64 in tablespace SYSTEM
Here is my trigger query.
create or replace TRIGGER TGR_IPCOLO_BIL
BEFORE INSERT ON ipcolo_ipfee_calc_bil
for each row
begin
IF INSERTING THEN
IF :NEW."ID" IS NULL THEN
select SEQ_IPCOLO_IPFEE_BIL.nextval into :NEW."ID" from dual;
end if;
END IF;
end;

That error sounds pretty bad (I never saw it before) ... internal dictionary tables?! What is error code? ORA-xxxxx?
Meanwhile, trigger can be simplified to this:
create or replace trigger trg_ipcolo_bil
before insert on ipcolo_ipfee_calc_bil
for each row
begin
:new.id := nvl(:new.id, seq_ipolo_ipfee_bil.nextval);
end;
/
You don't have to check if inserting; what else could it be, if it fires before insert? Also, you don't need select ... into - use sequence directly. nvl makes sure you won't overwrite id if you provided it.
Also, consider using identity column instead, if your database version supports it.

Related

Oracle - Update statement in Stored Procedure does not work once in a while

We have a stored procedure that inserts data into a table from some temporary tables in oracle database. There is an update statement after the insert that updates a flag in the same table based on certain checks. At the end of the stored procedure commit happens.
The problem is that the update works on 95% cases but in some cases it fails to update. When we try to run it again without changing anything, it works. Even trying to execute the same stored procedure on the same data at some other time, works perfectly. I haven't found any issues in the logic in the stored procedure. I feel there is some database level issue which we are not able to find (maybe related to concurrency). Any ideas on this would be very helpful.
Without seeing the source code we will just be guessing. The most obvious suggestion that I can think of is that it hits an exception somewhere along the way in some cases and never gets as far as the commit. Another possibility is that there is a lock on the table during execution when it fails.
Probably the best thing to investigate further would be to add an exception handler that writes the exceptions to some table or file and see what error is raised e.g.
-- create a logging table
create table tmp_error_log (timestamp timestamp(0), Error_test varchar2(1000));
-- add a variable to your procedure declaration
v_sql varchar2(1000);
-- add an exception handler just before the final end; statement on your procedure
exception
when others then
begin
v_sql := 'insert into tmp_error_log values(''' ||
to_char(sysdate, 'DD-MON-YYYY HH24:MI:SS') || ''', ''' || SQLERRM || ''')';
dbms_output.put_line(v_sql);
execute immediate v_sql;
commit;
end;
-- see what you get in the table
select * from tmp_error_log;

Oracle DB - identifier too long

I have created a connection in SQL Developer and added several tables to database. Also, I have defined some triggers. They all work well except for one that gives "identifier too long" error. I am aware of 30 character limit, but i can't see what causes this particular error. With this code, I'm trying to implement the Short-circuit keys.
Tables:
Izvestaj (IzvestajID, Datum, Opis, Tekst, PredmerID, NarucilacID, OsobaID, IzvrsilacID)
Predmer (PredmerID, Datum, Naziv, IzvrsilacID, LokacijaID)
Izvrsilac (IzvrsilacID, Naziv)
Italic values represent the primary keys of relations (tables).
Triggers:
create or replace TRIGGER "T_IZM_IZV"
AFTER UPDATE OF IZVRSILACID ON PREDMER
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'DISABLE');
UPDATE IZVESTAJ SET IZVRSILACID=:NEW.IZVRSILACID
WHERE PREDMERID=:NEW.PREDMERID;
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'ENABLE');
END;
create or replace TRIGGER "T_ZABRANA_IZM_IZV"
BEFORE UPDATE OF IzvrsilacID ON Izvestaj
FOR EACH ROW
BEGIN
RAISE_APPLICATION_ERROR(-20000, 'Direct altering of IzvrsilacID is forbidden');
END;
I have added some rows to table "Predmer" (Izvrsilac and Izvestaj also have some values inserted) and when I try to change value of column "IzvrsilacID" (foreign key), i get an error:
UPDATE "KORISNIK"."PREDMER" SET IZVRSILACID = '1' WHERE ROWID = 'AAAFBRAABAAALDxAAB' AND ORA_ROWSCN = '675526'
ORA-00972: identifier is too long
ORA-06512: at "KORISNIK.T_IZM_IZV", line 4
ORA-04088: error during execution of trigger 'KORISNIK.T_IZM_IZV'
One error saving changes to table "KORISNIK"."PREDMER":
Row 2: ORA-00972: identifier is too long
ORA-06512: at "KORISNIK.T_IZM_IZV", line 4
ORA-04088: error during execution of trigger 'KORISNIK.T_IZM_IZV'
What could cause this error? I've tried several things, even renaming triggers, tables and columns to one-letter names, but without any success.
P.S. Sorry about naming. I didn't want to translate table and column names to English because it would differ their length, which seems to cause an error in the first place.
These lines:
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'DISABLE');
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'ENABLE');
Should look like this:
EXECUTE IMMEDIATE ('ALTER TRIGGER '||'T_ZABRANA_IZM_IZV'||' DISABLE');
EXECUTE IMMEDIATE ('ALTER TRIGGER '||'T_ZABRANA_IZM_IZV'||' ENABLE');
Note the added spaces.
Without the spaces added, you were trying execute:
ALTER TRIGGERT_ZABRANA_IZM_IZVDISABLE
and
ALTER TRIGGERT_ZABRANA_IZM_IZVENABLE
which clearly isn't going to work.
Hope that helps.

Oracle Trigger inserting row into custom table

I have a Post-Insert Oracle trigger that is simply going to be used to insert a row into a table when the triggered table has a record added to it. My code is a simple insert:
BEGIN
INSERT INTO R5CHECKLISTMAP(CLM_CHKLINECODE, CLM_SYSTEMCODE)
VALUES(10, 'TEST');
END;
However, I get the error:
ORA 01006 - Bind Variable does not exist POST-INSERT 10 Before Binding
I know this has to be something simple, but I cannot figure out what the problem could be.

How to create a table and insert in the same statement

I'm new to Oracle and I'm struggling with this:
DECLARE
cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO cnt FROM all_tables WHERE table_name like 'Newtable';
IF(cnt=0) THEN
EXECUTE IMMEDIATE 'CREATE TABLE Newtable ....etc';
END IF;
COMMIT;
SELECT COUNT(*) INTO cnt FROM Newtable where id='something'
IF (cnt=0) THEN
EXECUTE IMMEDIATE 'INSERT INTO Newtable ....etc';
END IF;
END;
This keeps crashing and gives me the "PL/SQL: ORA-00942:table or view does not exist" on the insert-line. How can I avoid this? Or what am I doing wrong? I want these two statements (in reality it's a lot more of course) in a single transaction.
It isn't the insert that is the problem, it's the select two lines before. You have three statements within the block, not two. You're selecting from the same new table that doesn't exist yet. You've avoided that in the insert by making that dynamic, but you need to do the same for the select:
EXECUTE IMMEDIATE q'[SELECT COUNT(*) FROM Newtable where id='something']'
INTO cnt;
SQL Fiddle.
Creating a table at runtime seems wrong though. You said 'for safety issues the table can only exist if it's filled with the correct dataset', which doesn't entirely make sense to me - even if this block is creating and populating it in one go, anything that relies on it will fail or be invalidated until this runs. If this is part of the schema creation then making it dynamic doesn't seem to add much. You also said you wanted both to happen in one transaction, but the DDL will do an implicit commit, you can't roll back DDL, and your manual commit will start a new transaction for the insert(s) anyway. Perhaps you mean the inserts shouldn't happen if the table creation fails - but they would fail anyway, whether they're in the same block or not. It seems a bit odd, anyway.
Also, using all_tables for the check could still cause this to behave oddly. If that table exists in another schema, you create will be skipped, but you select and insert might still fail as they might not be able to see, or won't look for, the other schema version. Using user_tables or adding an owner check might be a bit safer.
Try the following approach, i.e. create and insert are in two different blocks
DECLARE
cnt NUMBER;
BEGIN
SELECT COUNT (*)
INTO cnt
FROM all_tables
WHERE table_name LIKE 'Newtable';
IF (cnt = 0)
THEN
EXECUTE IMMEDIATE 'CREATE TABLE Newtable(c1 varchar2(256))';
END IF;
END;
DECLARE
cnt2 NUMBER;
BEGIN
SELECT COUNT (*)
INTO cnt2
FROM newtable
WHERE c1 = 'jack';
IF (cnt2 = 0)
THEN
EXECUTE IMMEDIATE 'INSERT INTO Newtable values(''jill'')';
END IF;
END;
Oracle handles the execution of a block in two steps:
First it parses the block and compiles it in an internal representation (so called "P code")
It then runs the P code (it may be interpreted or compiled to machine code, depending on your architecture and Oracle version)
For compiling the code, Oracle must know the names (and the schema!) of the referenced tables. Your table doesn't exist yet, hence there is no schema and the code does not compile.
To your intention to create the tables in one big transaction: This will not work. Oracle always implicitly commits the current transaction before and after a DDL statement (create table, alter table, truncate table(!) etc.). So after each create table, Oracle will commit the current transaction and starts a new one.

creating insert trigger error

i'm trying to create a trigger that sets the id from a predefined sequence.
CREATE SEQUENCE seq_list_status
START WITH 1
INCREMENT BY 1
;
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
select seq_list_status.nextval into :new.id from dual;
/
i'm getting the error below while creating the trigger
Error starting at line 1 in command:
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
select seq_list_status.nextval into :new.id from dual
Error at Command Line:4 Column:4
Error report:
SQL Error: ORA-04079: invalid trigger specification
04079. 00000 - "invalid trigger specification"
*Cause: The create TRIGGER statement is invalid.
*Action: Check the statement for correct syntax.
i googled it but it seems all ok. any idea for what could be wrong?
Triggers are program units. Consequently we must wrap the code body in BEGIN and END. Try this
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
BEGIN
select seq_list_status.nextval into :new.id from dual;
END;
/
Unfortunately the examples in the SQL Reference are not as helpful as we would like. But it does link to other useful documents, such as the App Developers Guide.
you are missing the begin end
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
BEGIN
select seq_list_status.nextval into :new.id from dual;
END;
/

Resources