Two options:
- One using
INSERT INTO ... SELECT
with a LEFT OUTER JOIN
; and
- The other using
MERGE
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE city (
ID NUMBER(2) PRIMARY KEY,
NAME VARCHAR2(20)
);
INSERT INTO city
SELECT 1, 'City Name' FROM DUAL;
CREATE TABLE city_errors (
ID NUMBER(2),
NAME VARCHAR2(20),
TS TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ERROR VARCHAR2(20)
);
Query 1:
DECLARE
city_id CITY.ID%TYPE := 2;
city_name CITY.NAME%TYPE := 'City Name';
namingError EXCEPTION;
PRAGMA EXCEPTION_INIT( namingError, -20001 );
BEGIN
INSERT INTO city ( id, name )
SELECT city_id,
city_name
FROM DUAL d
LEFT OUTER JOIN
city c
ON ( c.name = city_name )
WHERE c.id IS NULL;
IF SQL%ROWCOUNT = 0 THEN
RAISE namingError;
END IF;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- Do something when duplicate ID found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate ID' );
WHEN namingError THEN
-- Do something when duplicate Name found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate Name' );
END;
Results:
Query 2:
DECLARE
city_id CITY.ID%TYPE := 3;
city_name CITY.NAME%TYPE := 'City Name';
namingError EXCEPTION;
PRAGMA EXCEPTION_INIT( namingError, -20001 );
BEGIN
MERGE INTO city c
USING ( SELECT city_id AS id,
city_name AS name
FROM DUAL ) d
ON ( c.Name = d.Name )
WHEN NOT MATCHED THEN
INSERT VALUES ( d.id, d.name );
IF SQL%ROWCOUNT = 0 THEN
RAISE namingError;
END IF;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- Do something when duplicate ID found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate ID' );
WHEN namingError THEN
-- Do something when duplicate Name found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate Name' );
END;
Results:
Query 3:
SELECT * FROM City
Results:
| ID | NAME |
|----|-----------|
| 1 | City Name |
Query 4:
SELECT * FROM City_Errors
Results:
| ID | NAME | TS | ERROR |
|----|-----------|--------------------------------|----------------|
| 2 | City Name | January, 02 2014 20:01:49+0000 | Duplicate Name |
| 3 | City Name | January, 02 2014 20:01:49+0000 | Duplicate Name |