handling exception for insert into select from - oracle

SCHEMA 1
I have table transaction table
create table TXN_HEADER
(
txn_id NUMBER(10) not null,
txn_Date date
product_id NUMBER(10),
company_id NUMBER(10),
dealer_id NUMBER(10),
tran_amt number(10,2)
)
The above table having foreign key references to product.product_id and company.company_id.
This table having 5m rows
SCHEMA 2
create table TXN_HEADER_REPORTS
(
txn_id NUMBER(10) not null,
txn_Date date
product_id NUMBER(10),
company_id NUMBER(10),
dealer_id NUMBER(10),
tran_amt number(10,2)
)
here also we have the same constraints , having foreign key references to product.product_id and company.company_id.
in schema 2 we are trying to insert all the rows from schemea 1 to schema 2 in one shot, like this
begin
insert into TXN_HEADER_REPORTS (
txn_id, txn_Date ,product_id,company_id , dealer_id , tran_amt)
select
txn_id, txn_Date ,product_id,company_id , dealer_id , tran_amt
from schema1.TXN_HEADER;
commit;
exception
when others then
< ... procedure to log the errors >
end;
now we are trying to execute the above procedure , and it failed due to foreign key constraint of one rows. But entire my transaction rollback. Actually i dont want to use cursor to process the rows one by one , at it takes long time. So i used to "insert into .. SElect from " but due to constraints of 1 row all my transaction not moved to schema2.txn_Extract_hdr.
Is there any way to trap only that failed and to process the other rows without terminating
Please advice ..

You can create an error log table, and then use a single insert:
exec dbms_errlog.create_error_log(dml_table_name => 'TXN_HEADER_REPORTS');
insert into TXN_HEADER_REPORTS ( txn_id, txn_Date ,product_id,company_id ,
dealer_id , tran_amt)
select txn_id, txn_Date ,product_id,company_id , dealer_id , tran_amt
from schema1.TXN_HEADER
log errors into ERR$_TXN_HEADER_REPORTS reject limit unlimited;
Any rows that can't inserted will be recorded in the ERR table. Note that this is plain SQL, it doesn't need to be in a PL/SQL block.
Read more in the documentation.

I don't understand your constraint.
Does your insert fail because the product_id and company_id don't exists in schema2?
In that case, it may be better to insert the missing company and product records before you insert records into TXN_HEADER_REPORTS of schema2.
insert into company com_sch2
(col1, col2, col2,...)
select col1, col2, col3, ...
from schema1.company com_sch1
where not exists (select 'x'
from company com2
where com2.company_id = com_sch1.company_id);
And the seem for the product table.

Related

SQL: ORA-02291: integrity constraint violated - parent key not found

I am creating this code SQL code and I keep getting the same error from every line of the insert statements after the errors begin here statement. the error is, ORA-02291: integrity constraint violated - parent key not found. I think it has something to do with the employee section constraint EMPSUPERVRFK but, that is the only constraint that the error message would lead to.
-- keep these two commands at the top of every sql file
set echo on
set linesize 120
delete from Employee;
commit;
-- insert only managers first with their dno is null
INSERT INTO Employee VALUES
('James','E','Borg',888665555,'10-NOV-1937','450 Stone, Houston, TX','M',55000,null,null);
INSERT INTO Employee VALUES
('Franklin','T','Wong',333445555, to_date('1955-12-08', 'YYYY-MM-DD'), '638 Voss, Houston, TX','M',40000,888665555,null);
INSERT INTO Employee VALUES
('Jennifer','J','Zelaya',987654321,'20-JUN-1941','291 Berry, Bellaire, TX','F',43000,888665555,null);
delete from Department;
commit;
insert into Department values ('Research',5,333445555,'22-MAY-1988');
insert into Department values ('Headquarters',1,888665555,'19-JUN-1981');
insert into Department values ('Administration',1,888665555,'01-JAN-1995');
-- now, update employee.dno for managers
UPDATE Employee SET dno = 1 WHERE ssn = 888665555;
UPDATE Employee SET dno = 5 WHERE ssn = 333445555;
-- need to update the rest of managers
-- insert the rest of non-manager employees, supervisors first
--errors begin here
delete from Employee;
commit;
INSERT INTO Employee VALUES ('John','B','Smith',123456789,'09-JAN-1965','731 Fondren, Houston, TX','M',30000,333445555,5);
insert into Employee values ('Alica','J','Zelya',999887777,'19-JAN-1968','3321 Castle, Spring, TX','F',25000,987654321,4);
insert into Employee values ('Ramesh','K','Narayan',666884444,'15-SEP-1962', '975 Fire Oak, Humnle, TX','M',38000,333445555,5);
insert into Employee values ('Joyce','A','English',453453453,'31-JUL-1972','5631 Rice, Houston, TX','F',25000,333445555,5);
insert into Employee values ('Ahmad','V','Jabbar',987987987,'29-MAR-1969','980 Dallas, Houston, TC','M',25000,987654321,4);
--Project
delete from PROJECT;
commit;
insert into PROJECT values ('ProductY',2,'Sugarland',5);
insert into PROJECT values ('ProductZ',3,'Houston',5);
insert into PROJECT values ('Computerication',10,'Stafford',4);
insert into PROJECT values ('Reorganization',20,'Houston',1);
insert into PROJECT values ('Newbenefits',30,'Stafford',4);
--dept_Locations
delete from DEPT_LOCATIONS;
commit;
insert into DEPT_LOCATIONS values (1, 'Houston');
insert into DEPT_LOCATIONS values (4,'Stafford');
insert into DEPT_LOCATIONS values (5,'Bellaire');
insert into DEPT_LOCATIONS values (5,'Sugarland');
insert into DEPT_LOCATIONS values (5,'Houston');
--works_on 16
delete from WORKS_ON;
commit;
insert into WORKS_ON values (123456789,1,32.5);
insert into WORKS_ON values (123456789,2,7.5);
insert into WORKS_ON values (666884444,3,40.0);
insert into WORKS_ON values (453453453,1,20.0);
insert into WORKS_ON values (453453453,2,20.0);
insert into WORKS_ON values (333445555,2,10.0);
insert into WORKS_ON values (333445555,3,10.0);
insert into WORKS_ON values (333445555,10,10.0);
insert into WORKS_ON values (333445555,20,10.0);
insert into WORKS_ON values (999887777,30,30.0);
insert into WORKS_ON values (999887777,10,10.0);
insert into WORKS_ON values (987987987,10,35.0);
insert into WORKS_ON values (987987987,30,5.0);
insert into WORKS_ON values (987654321,30,20.0);
insert into WORKS_ON values (987654321,20,15.0);
insert into WORKS_ON values (888665555,20,null);
--dependent 7
delete from DEPENDENT;
commit;
insert into DEPENDENT values (333445555,'Alice','F','05-APR-1986','Daughter');
insert into DEPENDENT values (333445555,'Theodore','M','25-OCT-1983','Son');
insert into DEPENDENT values (333445555,'Joy','F', '03-MAY-1958','Spouse');
insert into DEPENDENT values (987654321,'Abner','M', '28-FEB-1942','Spouse');
insert into DEPENDENT values (123456789,'Michael','M','04-JAN-1988','Son');
insert into DEPENDENT values (123456789,'Alice','F','30-DEC-1988','Daughter');
insert into DEPENDENT values (123456789,'Elizabeth','F', '05-MAY-1967','Spouse');
-----------------------------------------------------------------------------------
set echo on
set linesize 120
drop table Employee cascade constraints;
commit;
create table Employee
(
fname varchar2(15),
minit varchar2(1), -- can be char
lname varchar2(15),
ssn number,
bdate date,
address varchar2(50),
sex varchar2(1) CHECK(Sex = 'M' or Sex = 'F'),
salary number CHECK(20000 <= salary AND 100000 >= salary),
superssn number,
dno number DEFAULT 0,
constraint EMPPK
primary key(ssn),
constraint EMPSUPERVRFK
foreign key(superssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Department cascade constraints;
commit;
create table Department
(
dname varchar2(15),-- NOT NULL,
dnumber number,
mgrssn number,
mgrstartdate date,
constraint DEPTPK
primary key(dnumber),
constraint DEPTMGRFK
foreign key(mgrssn) references Employee(ssn)
ON DELETE SET NULL
);
alter table Employee add
constraint EMPDEPTFK foreign key(dno) references Department(dnumber)
ON DELETE SET NULL;
drop table DEPT_LOCATIONS;
create table DEPT_LOCATIONS
(
Dnumber number,
Dlocation varchar2(15),
constraint PK_DnoDloc primary key(Dnumber,Dlocation)
);
COMMIT;
drop table PROJECT;
create table PROJECT
(
Pname varchar2(15),
Ponumber number primary key,
Plocation varchar2 (15),
Dnum number,
foreign key (Dnum) references Department(dnumber)
);
Commit;
drop table DEPENDENT;
create table DEPENDENT
(
Essn number,
Dependent_name varchar2(15),
Sex Char,
Bdate Date,
Relationship varchar2(15),
foreign key(Essn) references Employee(ssn) --
ON DELETE SET NULL,
constraint PK_essn
primary key(Essn,Dependent_name)
);
COMMIT;
drop table WORKS_ON;
create table WORKS_ON
(
Essn number,
Pno number,
Hours number,
foreign key(Essn) references Employee(ssn)--
ON DELETE SET NULL,
foreign key(Pno) references PROJECT(Ponumber)
ON DELETE SET NULL,
constraint PK_SSN
primary key(Essn, Pno)
);
commit;
----------------------------------------------------------------
-- keep these two commands at the top of every sql file
set echo on
set linesize 120
-- test queries, not to be submitted
select count(*) from employee;
select count(*) as DEPT_COUNT from department;
-- comment out the above queries for your homework
-- a the first name, last name of employees who work in department 5.
select fname, lname from employee where dno = 5;
-- b the first name, last name of every employee and name of his/her department
select E.fname as FIRST_NAME, E.lname LAST_NAME, D.dname DEPARTMENT_NAME
from employee E, department D
where E.dno = D.dnumber;
--c The first name, last name of employees who works at the 'Research' department
select e.fname , e.lname , Dname
from employee e inner join department d on e.dno=d.dname
where d.name ='Research';
--d. The first name, last name of employee who is the manager of the 'Research' department
select e.fname , e.lname , Dname
from employee e inner join department d on e.dno=d.dname
where d.name ='Research' and e.super_ssn=d.mgr_ssn;
--e. The first name, last name of employees who works on the 'Computerization' project.
select e.fname,e.lname
from employee e inner join department d on e.dno=d.dnumber inner join project p on d.dnumber=p.dnum
where p.pname="Computerization";
this happens because you are inserting values to table that depends on other table that is still empty, you should insert on that table first before this one
for example, suppose you have employee table, and department table, in which every employee must be assigned to a department, so when you input employee Bob to department IT, it would result in error, since there is no IT yet in department table. so you need to input IT on department table, then you can input Bob to employee table
or, you can disable integrity check when importing sql, but this setting is different for each DB engine, so I can't give you an example

"ORA-00001: unique constraint (constraint_name) violated" Error even though I have NOT EXISTS check

I am trying to insert some values in the table through the application and get the issue "ORA-00001: unique constraint (constraint_name) violated". I have the below table:
CREATE TABLE EMPLOYEE
(
EMP_ID VARCHAR2(32) NOT NULL,
NAME VARCHAR2(30) NOT NULL,
TIME TIMESTAMP(3),
PRIMARY KEY(EMP_ID)
);
I have below statement in procedure and it is failing at this INSERT statement even though I have NOT EXISTS check before inserting:
INSERT INTO EMPLOYEE
(EMP_ID, NAME, TIME)
( SELECT v_empid ,
sys_context('USERENV','SID'),
SYSTIMESTAMP+INTERVAL '10' SECOND
FROM DUAL
WHERE NOT EXISTS ( SELECT 1
FROM EMPLOYEE
WHERE EMP_ID = v_empid) );
The above procedure is getting invoked from multiple services almost at the same time, Is there something issue with the parallel transactions like multiple sessions are trying to insert into the same table?
Any help is appreciated in this, thanks in advance.
To me it looks like 2 sessions are trying to insert same user at the same time.
Here how I reproduced it:
Step 1. Session A:
INSERT INTO test_EMPLOYEE(EMP_ID, NAME, TIME)
(SELECT 123, sys_context('USERENV','SID'), SYSTIMESTAMP+INTERVAL '10' SECOND
FROM DUAL
WHERE NOT EXISTS ( SELECT 1 FROM test_EMPLOYEE WHERE EMP_ID = 123));
Step 2. Session B:
-- same query as Session A
INSERT INTO test_EMPLOYEE(EMP_ID, NAME, TIME)
(SELECT 123, sys_context('USERENV','SID'), SYSTIMESTAMP+INTERVAL '10' SECOND
FROM DUAL
WHERE NOT EXISTS ( SELECT 1 FROM test_EMPLOYEE WHERE EMP_ID = 123));
Step 3. Session A:
commit;
Voila: session B fails with constraint violation
So I believe it's users or something outside of database causing the error

Oracle rename table to temp table, create new, then move data from temp to new table

I have a table named MESSAGE_ID:
MESSAGE_ID VARCHAR2(36 BYTE) PRIMARY KEY
DATE TIMESTAMP(6)
STATUS VARCHAR2(200 BYTE)
I want to create a new table to add a new field which should be the primary key.
alter table MESSAGE_ID rename to MESSAGE_ID_OLD;
CREATE TABLE MESSAGE_ID
(
MY_ID NUMBER NOT NULL,
MESSAGE_ID VARCHAR2(36) NOT NULL,
DATE TIMESTAMP,
STATUS VARCHAR2(200),
PRIMARY KEY(MY_ID)
);
Now I want to take everything from the MESSAGE_ID_OLD and insert it into the new table, however I need to put some thing into MY_ID, some random number or something.
This is what I have, but it gives me error:
INSERT INTO MESSAGE_ID (MY_ID, MESSAGE_ID, DATE, STATUS)
(SELECT MY_SEQUENCE.nextval from dual), (SELECT MESSAGE_ID, DATE, STATUS FROM MESSAGE_ID_OLD));
Then I want to delete the old table:
DROP TABLE MESSAGE_ID_OLD;
The Insert statement you are using is not correct.
It should be
INSERT INTO MESSAGE_ID (
MY_ID
,MESSAGE_ID
,DATE_t
,STATUS
)
SELECT MY_SEQUENCE.nextval AS my_id
,MESSAGE_ID
,DATE_t
,STATUS
FROM MESSAGE_ID_OLD;
Also, change the column "DATE" to something else meaningful, as it's a reserved keyword.

Validate ALL the constraints when inserting a record in Oracle [duplicate]

I have a table in Oracle with several constraints. When I insert a new record and not all constraints are valid, then Oracle raise only the "first" error. How to get all violations of my record?
CREATE TABLE A_TABLE_TEST (
COL_1 NUMBER NOT NULL,
COL_2 NUMBER NOT NULL,
COL_3 NUMBER NOT NULL,
COL_4 NUMBER NOT NULL
);
INSERT INTO A_TABLE_TEST values (1,null,null,2);
ORA-01400: cannot insert NULL into ("USER_4_8483C"."A_TABLE_TEST"."COL_2")
I would like to get something like this:
Column COL_2: cannot insert NULL
Column COL_3: cannot insert NULL
This would be also sufficient:
Column COL_2: not valid
Column COL_3: not valid
Of course I could write a trigger and check each column individually, but I like to prefer constraints rather than triggers, they are easier to maintain and don't require manually written code.
Any idea?
There no straightforward way to report all possible constraint violations. Because when Oracle stumble on first violation of a constraint, no further evaluation is possible, statement fails, unless that constraint is deferred one or the log errors clause has been included in the DML statement. But it should be noted that log errors clause won't be able to catch all possible constraint violations, just records first one.
As one of the possible ways is to:
create exceptions table. It can be done by executing ora_home/rdbms/admin/utlexpt.sql script. The table's structure is pretty simple;
disable all table constraints;
execute DMLs;
enable all constraints with exceptions into <<exception table name>> clause. If you executed utlexpt.sql script, the name of the table exceptions are going to be stored would be exceptions.
Test table:
create table t1(
col1 number not null,
col2 number not null,
col3 number not null,
col4 number not null
);
Try to execute an insert statement:
insert into t1(col1, col2, col3, col4)
values(1, null, 2, null);
Error report -
SQL Error: ORA-01400: cannot insert NULL into ("HR"."T1"."COL2")
Disable all table's constraints:
alter table T1 disable constraint SYS_C009951;
alter table T1 disable constraint SYS_C009950;
alter table T1 disable constraint SYS_C009953;
alter table T1 disable constraint SYS_C009952;
Try to execute the previously failed insert statement again:
insert into t1(col1, col2, col3, col4)
values(1, null, 2, null);
1 rows inserted.
commit;
Now, enable table's constraints and store exceptions, if there are any, in the exceptions table:
alter table T1 enable constraint SYS_C009951 exceptions into exceptions;
alter table T1 enable constraint SYS_C009950 exceptions into exceptions;
alter table T1 enable constraint SYS_C009953 exceptions into exceptions;
alter table T1 enable constraint SYS_C009952 exceptions into exceptions;
Check the exceptions table:
column row_id format a30;
column owner format a7;
column table_name format a10;
column constraint format a12;
select *
from exceptions
ROW_ID OWNER TABLE_NAME CONSTRAINT
------------------------------ ------- ------- ------------
AAAWmUAAJAAAF6WAAA HR T1 SYS_C009951
AAAWmUAAJAAAF6WAAA HR T1 SYS_C009953
Two constraints have been violated. To find out column names, simply refer to user_cons_columns data dictionary view:
column table_name format a10;
column column_name format a7;
column row_id format a20;
select e.table_name
, t.COLUMN_NAME
, e.ROW_ID
from user_cons_columns t
join exceptions e
on (e.constraint = t.constraint_name)
TABLE_NAME COLUMN_NAME ROW_ID
---------- ---------- --------------------
T1 COL2 AAAWmUAAJAAAF6WAAA
T1 COL4 AAAWmUAAJAAAF6WAAA
The above query gives us column names, and rowids of problematic records. Having rowids at hand, there should be no problem to find those records that cause constraint violation, fix them, and re-enable constraints once again.
Here is the script that has been used to generate alter table statements for enabling and disabling constraints:
column cons_disable format a50
column cons_enable format a72
select 'alter table ' || t.table_name || ' disable constraint '||
t.constraint_name || ';' as cons_disable
, 'alter table ' || t.table_name || ' enable constraint '||
t.constraint_name || ' exceptions into exceptions;' as cons_enable
from user_constraints t
where t.table_name = 'T1'
order by t.constraint_type
You would have to implement a before-insert trigger to loop through all the conditions that you care about.
Think about the situation from the database's perspective. When you do an insert, the database can basically do two things: complete the insert successfully or fail for some reason (typically a constraint violation).
The database wants to proceed as quickly as possibly and not do unnecessary work. Once it has found the first complaint violation, it knows that the record is not going into the database. So, the engine wisely returns an error and stops checking further constraints. There is no reason for the engine to get the full list of violations.
In the meantime I found a lean solution using deferred constraints:
CREATE TABLE A_TABLE_TEST (
COL_1 NUMBER NOT NULL DEFERRABLE INITIALLY DEFERRED,
COL_2 NUMBER NOT NULL DEFERRABLE INITIALLY DEFERRED,
COL_3 NUMBER NOT NULL DEFERRABLE INITIALLY DEFERRED,
COL_4 NUMBER NOT NULL DEFERRABLE INITIALLY DEFERRED
);
INSERT INTO A_TABLE_TEST values (1,null,null,2);
DECLARE
CHECK_CONSTRAINT_VIOLATED EXCEPTION;
PRAGMA EXCEPTION_INIT(CHECK_CONSTRAINT_VIOLATED, -2290);
REF_CONSTRAINT_VIOLATED EXCEPTION;
PRAGMA EXCEPTION_INIT(REF_CONSTRAINT_VIOLATED , -2292);
CURSOR CheckConstraints IS
SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME
FROM USER_CONSTRAINTS
JOIN USER_CONS_COLUMNS USING (TABLE_NAME, CONSTRAINT_NAME)
WHERE TABLE_NAME = 'A_TABLE_TEST'
AND DEFERRED = 'DEFERRED'
AND STATUS = 'ENABLED';
BEGIN
FOR aCon IN CheckConstraints LOOP
BEGIN
EXECUTE IMMEDIATE 'SET CONSTRAINT '||aCon.CONSTRAINT_NAME||' IMMEDIATE';
EXCEPTION
WHEN CHECK_CONSTRAINT_VIOLATED OR REF_CONSTRAINT_VIOLATED THEN
DBMS_OUTPUT.PUT_LINE('Constraint '||aCon.CONSTRAINT_NAME||' at Column '||aCon.COLUMN_NAME||' violated');
END;
END LOOP;
END;
It works with any check constraint (not only NOT NULL). Checking FOREIGN KEY Constraint should work as well.
Add/Modify/Delete of constraints does not require any further maintenance.

ORA-00942 on INSERT to a newly created table

I'm doing an evaluation of FLYWAY and running a very simple script that creates a new table and insert a row to that table. The table creates successfully but I get an ORA-942 error on the INSERT. I have tried every permutation I can think of using upper/lower case and quoted and unquoted schema and table names. I have also tried separating out the INSERT statement into different script from the CREATE statement - all to no avail. Can anyone help explain the format flyway needs for the INSERT statements?
Here are the statements from my most recent attempt. I have tried the same statements with quotes around the table_name, with all lower case, with no quotes around the schema - nothing works. Logged directly into the database as SYS, I can describe the table with this command:
desc "FLYWAY_USER".department
CREATE TABLE "FLYWAY_USER".DEPARTMENT
( DEPARTMENT_id NUMBER(3) NOT NULL,
DEPARTMENT VARCHAR2(64) NOT NULL,
display_name VARCHAR2(64) NOT NULL,
description VARCHAR2(400),
create_date DATE NOT NULL,
update_date DATE NOT NULL,
created_by VARCHAR2(80) NOT NULL,
updated_by VARCHAR2(80) NOT NULL )
TABLESPACE users;
INSERT INTO "FLYWAY_USER".DEPARTMENT
( DEPARTMENT_id,
DEPARTMENT,
display_name,
description,
create_date,
update_date,
created_by,
updated_by )
VALUES
( ( SELECT Nvl( Max(DEPARTMENT_id), 0) + 1 FROM DEPARTMENT ),
'HUMAN_RESOURCES',
'Human Resources',
'The best place to eat smores or get a raise.',
Sysdate,
Sysdate,
'AT09001',
'AT09001' );
Thanks
Logged directly into the database as SYS
Use better a dedicated application user.
Anyway if you use a different user that the schema owner of your objects (FLYWAY_USER) you must qualify ALL your references.
especially
VALUES
( ( SELECT Nvl( Max(DEPARTMENT_id), 0) + 1 FROM DEPARTMENT ),
should be
VALUES
( ( SELECT Nvl( Max(DEPARTMENT_id), 0) + 1 FROM FLYWAY_USER.DEPARTMENT ),

Resources