INSERT ALL statement in Oracle failing to insert - oracle

I have multiple rows to insert in a table.
There are some constraints in the table which fails for few of the rows.
But with INSERT ALL statement, when it finds the first insert with constraint fails, it stops inserting to oracle db and rest of the data which are proper is also not inserted.
Will it be working this way only. Or do we have any method in which insert all valid data and ignore the other inserts in the INSERT ALL.

when it finds the first insert with constraint fails, it stops inserting to oracle db and rest of the data which are proper is also not inserted. Will it be working this way only.
Yes, it is designed to work that way. INSERT ALL statement will fail to insert if any one row errors out.
For example,
SQL> CREATE TABLE t(a NUMBER);
Table created.
SQL> ALTER TABLE t ADD CONSTRAINT t_unique UNIQUE(a);
Table altered.
SQL> INSERT INTO t(a) VALUES(1);
1 row created.
SQL> INSERT ALL
2 INTO t (a) VALUES (1)
3 INTO t (a) VALUES (2)
4 INTO t (a) VALUES (3)
5 SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.T_UNIQUE) violated
SQL> SELECT * FROM t;
A
----------
1
If you want other values to be inserted which are correct, then put them as individual insert statements and execute all the insert statements as a script.
For example,
SQL> CREATE TABLE t(a NUMBER);
Table created.
SQL> ALTER TABLE t ADD CONSTRAINT t_unique UNIQUE(a);
Table altered.
SQL> INSERT INTO t(A) VALUES(1);
1 row created.
SQL> INSERT INTO t(a) VALUES(1);
INSERT INTO t(a) VALUES(1)
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.T_UNIQUE) violated
SQL> INSERT INTO t(A) VALUES(2);
1 row created.
SQL> INSERT INTO t(A) VALUES(3);
1 row created.
SQL> SELECT * FROM t;
A
----------
1
2
3

Related

SQL Query alter table auto increment in SQL Plus Oracle 10g

I have this SQL Query and I am trying to modify my column so it has an auto increment Property, But when I execute the query I either have a problem code ORA-00933 SQL command not properly ended
This is what I have tried
ALTER TABLE BF_USER DROP COLUMN USER_ID
ALTER TABLE BF_USER ADD USER_ID INT IDENTITY(1,1);
SQL*Plus is Oracle's command-line tool. In that case:
SQL> create table bf_user (user_id number, name varchar2(10));
Table created.
SQL> alter table bf_user drop column user_id;
Table altered.
SQL> alter table bf_user add user_id number generated always as identity;
Table altered.
Testing:
SQL> insert into bf_user(name) values ('Littlefoot');
1 row created.
SQL> select * from bf_user;
NAME USER_ID
---------- ----------
Littlefoot 1
SQL>
As you use Oracle 10g (which doesn't support identity columns), use combination of a sequence and a database trigger:
SQL> create table bf_user (user_id number, name varchar2(10));
Table created.
SQL> create sequence bf_seq;
Sequence created.
SQL> create or replace trigger trg_bi_bfu
2 before insert on bf_user
3 for each row
4 begin
5 select bf_seq.nextval into :new.user_id from dual;
6 end;
7 /
Trigger created.
SQL> insert into bf_user (name) values ('Nayeon');
1 row created.
SQL> select * from bf_user;
USER_ID NAME
---------- ----------
1 Nayeon
SQL>

Can i disable a trigger inside a trigger in oracle?

I have 2 triggers and two tables.
One(trigger) is to insert inside one column in the other table when a row in first table is inserted, the other one prevent insert and update in that column.
I want to know if there is a way i can disable the second trigger that prevents the insert/update during the execution of first trigger.
This is how I understood the question. See if it helps.
Sample tables:
SQL> create table test (id number);
Table created.
SQL> create table test_2 (id number);
Table created.
A trigger on test_2 which prevents inserts:
SQL> create or replace trigger trg2
2 before insert or update on test_2
3 for each row
4 begin
5 raise_application_error(-20000, 'Not allowed');
6 end;
7 /
Trigger created.
Does it work?
SQL> insert into test_2 (id) values (1);
insert into test_2 (id) values (1)
*
ERROR at line 1:
ORA-20000: Not allowed
ORA-06512: at "SCOTT.TRG2", line 2
ORA-04088: error during execution of trigger 'SCOTT.TRG2'
Yes, it works.
Now, a trigger on test which is supposed to a) disable trg2 trigger and b) insert value into test_2. A straightforward code would then be
SQL> create or replace trigger trg1
2 before insert on test
3 for each row
4 begin
5 execute immediate 'alter trigger trg2 disable';
6 insert into test_2 (id) values (:new.id);
7 end;
8 /
Trigger created.
Let's test it:
SQL> insert into test (id) values (1);
insert into test (id) values (1)
*
ERROR at line 1:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SCOTT.TRG1", line 2
ORA-04088: error during execution of trigger 'SCOTT.TRG1'
Aha. Can't COMMIT in a trigger. Where is it? In dynamic SQL's alter trigger - it is a DDL and it implicitly commits. How to "fix" it? Make it (a trigger) an autonomous transaction:
SQL> create or replace trigger trg1
2 before insert on test
3 for each row
4 declare
5 pragma autonomous_transaction;
6 begin
7 execute immediate 'alter trigger trg2 disable';
8 insert into test_2 (id) values (:new.id);
9 end;
10 /
Trigger created.
SQL> insert into test (id) values (1);
insert into test (id) values (1)
*
ERROR at line 1:
ORA-06519: active autonomous transaction detected and rolled back
ORA-06512: at "SCOTT.TRG1", line 6
ORA-04088: error during execution of trigger 'SCOTT.TRG1'
That's another error; it says that - if we have an autonomous transaction - we have to either commit or roll back. Let's commit (because that's probably what you'd want to do):
SQL> create or replace trigger trg1
2 before insert on test
3 for each row
4 declare
5 pragma autonomous_transaction;
6 begin
7 execute immediate 'alter trigger trg2 disable';
8 insert into test_2 (id) values (:new.id);
9 commit;
10 end;
11 /
Trigger created.
SQL> insert into test (id) values (100);
1 row created.
SQL> select * From test;
ID
----------
100
SQL> select * from test_2;
ID
----------
100
SQL>
Right; now it works.
I suggest you re-read comments posted below your question, see this example and choose what to do.

How to add extra column in the INTO section of SQL Trigger

How to add an extra column (say column_2) in the below INTO section of my code along with my Column_1. I assume we can do that by adding comma (,) and just add column_2 (like this INTO :new.Column_1, new.column_2). I'm missing something?
create or replace trigger trigger_name
BEFORE INSERT
ON table_name
FOR EACH ROW
BEGIN
SELECT SEQUENCE_NUMBER.NEXTVAL
INTO :new.Column_1
FROM dual;
END;
It is easy to confirm whether you are right (or wrong). I hope you got the answer during the past 6 hours. If not, here's an example:
SQL> create table test
2 (id number,
3 datum date);
Table created.
SQL> create sequence seq_test;
Sequence created.
SQL> create or replace trigger trg_bi_test
2 before insert on test
3 for each row
4 begin
5 select seq_test.nextval, sysdate
6 into :new.id, :new.datum
7 from dual;
8 end;
9 /
Trigger created.
SQL> insert into test (id) values (-1);
1 row created.
SQL> select * From test;
ID DATUM
---------- -------------------
1 21.06.2019 21:54:08
SQL>

Can adding FK or PK constraints invalidate something?

I have a couple of tables with primary-foreign key relations but those constraints do not actually exist. Now I want to add them with an alter table statement.
Will those commands cause any object that depends on the tables to become invalid?
Thanks.
This is a good question. Let's poke the database and see. Here's the set up:
SQL> create table p23 (id number not null, col1 varchar2(10));
Table created.
SQL> create table c23 (id number not null, p_id number not null, col1 varchar2(10));
Table created.
SQL> create or replace procedure tst23
2 is
3 begin
4 insert into p23 values (1, 'ABC');
5 insert into c23 values (11, 1, 'DEF');
6 end;
7 /
Procedure created.
SQL> select status from user_objects where object_name = 'TST23';
STATUS
-------
VALID
SQL>
Everything is copacetic. Now we'll add some constraints.
SQL> alter table p23 add constraint p23_pk primary key (id);
Table altered.
SQL> select status from user_objects where object_name = 'TST23';
STATUS
-------
VALID
SQL> alter table c23 add constraint c23_p23_fk
2 foreign key (p_id) references p23;
Table altered.
SQL> select status from user_objects where object_name = 'TST23';
STATUS
-------
VALID
SQL>
All is still cool. But when we change a table's structure this happens...
SQL> alter table p23 add col2 date;
Table altered.
SQL> select status from user_objects where object_name = 'TST23';
STATUS
-------
INVALID
SQL>
... which is exactly what we would want.
Note that I ran these tests on 11gR2. Oracle introduced fine-grained dependency tracking in 11g, which made programmatic objects more robust when we run DDL on their dependencies. Find out more. So the outcome might be different in earlier versions. It pays to test.
" what is the reason for the procedure to become invalid?"
Structural changes such as adding, modifying or dropping a column potentially have an impact on referencing objects. The procedure had insert statements which didn't specify target columns. So adding a column introduced an ORA-00947: not enough values bug.
But suppose we employed good practice and specified columns?
SQL> create or replace procedure tst23
2 is
3 begin
4 insert into p23 (id, col1) values (1, 'ABC');
5 end;
6 /
Procedure created.
SQL> select status from user_objects where object_name = 'TST23';
STATUS
-------
VALID
SQL> alter table p23 add col4 number;
Table altered.
SQL> select status from user_objects where object_name = 'TST23';
STATUS
-------
VALID
SQL>
Now we're protected by fine-grained dependency tracking. Well, sort of. We shouldn't substitute dependency tracking for impact analysis:
SQL> alter table p23 add col5 date not null;
Table altered.
SQL> select status from user_objects where object_name = 'TST23';
STATUS
-------
VALID
SQL>
The procedure has a VALID state but it will still fail when we run it, because it doesn't populate the new mandatory column.

Count of table before and after insert inside a trigger

Is it possible to check the count of a table before any changes happen and the count after the insert and match them inside the same trigger?
for ex: old.count and new.count (before and after insert) ?
old.count and new.count (before and after insert)
Nothing stops you from using SELECT COUNT(*) in a before insert trigger. Of course, you won't do it in a after insert trigger, since a select count(*) on the same table on which an after trigger is defined would throw mutating table error. One way is autonomous transaction. But, in your case, it isn't that complex.
You could define a BEFORE INSERT TRIGGER and take the table count. The after insert count could be taken manually after the actual insert is done.
For example, I have a table t1 with one row. I have defined a before insert trigger on it, which would give me the table count before the insert happens.
SQL> DROP TABLE t1 PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE t1 (A NUMBER);
Table created.
SQL>
SQL> INSERT INTO t1 VALUES (1);
1 row created.
SQL>
SQL> SELECT * FROM t1;
A
----------
1
SQL>
SQL> CREATE OR REPLACE TRIGGER trg
2 BEFORE INSERT
3 ON t1
4 FOR EACH ROW
5
6 DECLARE
7 val number;
8 BEGIN
9 SELECT COUNT(*)
10 INTO val
11 FROM t1;
12
13 DBMS_OUTPUT.PUT_LINE('TABLE COUNT BEFORE INSERT = '||val);
14
15 END;
16 /
Trigger created.
SQL>
SQL> set serveroutput on
SQL> INSERT INTO t1 VALUES (1);
TABLE COUNT BEFORE INSERT = 1
1 row created.
SQL>
SQL> SELECT COUNT(*) FROM t1;
COUNT(*)
----------
2
SQL>
So, you see TABLE COUNT BEFORE INSERT = 1 and then after insert the count is 2.

Resources