Home » SQL & PL/SQL » SQL & PL/SQL » Identity column inserts duplicates with Insert All statement, unique constraint violation (Oracle database, 12.1.0.2, Any OS)
| Identity column inserts duplicates with Insert All statement, unique constraint violation [message #633352] |
Tue, 17 February 2015 00:06  |
Lalit Kumar B
Messages: 3174 Registered: May 2013 Location: World Wide on the Web
|
Senior Member |
|
|
This seems to be a big problem with Identity columns. The sequence of the Identity column doesn't progress to nextval when an Insert All statement is executed. Thus, inserting duplicate keys which raises ORA-00001: unique constraint violation error. Yes, it seems a obvious thing, as the same would happen if we use an explicit sequence instead of identity column. However, it was never an issue with the old trigger-sequence approach. Since, we create a row level trigger.
Set up -
DROP TABLE t PURGE;
CREATE TABLE t (
ID NUMBER GENERATED ALWAYS AS IDENTITY,
text VARCHAR2(50),
CONSTRAINT id_pk PRIMARY KEY (ID)
);
Test -
SQL> CREATE TABLE t (
2 ID NUMBER GENERATED ALWAYS AS IDENTITY,
3 text VARCHAR2(50),
4 CONSTRAINT id_pk PRIMARY KEY (ID)
5 );
Table created.
SQL>
SQL> INSERT ALL
2 INTO t (text) VALUES ('a')
3 INTO t (text) VALUES ('b')
4 INTO t (text) VALUES ('c')
5 INTO t (text) VALUES ('d')
6 SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.ID_PK) violated
SQL>
Though it works with a INSERT-INTO-SELECT -
SQL> INSERT INTO t(text) SELECT 'Level '||LEVEL FROM dual CONNECT BY LEVEL <= 4;
4 rows created.
SQL>
SQL> SELECT * FROM t;
ID TEXT
---------- --------------------------------------------------
2 Level 1
3 Level 2
4 Level 3
5 Level 4
SQL>
Disabling the constraint and subsequent insert reveals the issue -
SQL> ALTER TABLE t
2 DISABLE CONSTRAINT id_pk;
Table altered.
SQL>
SQL> INSERT ALL
2 INTO t (text) VALUES ('a')
3 INTO t (text) VALUES ('b')
4 INTO t (text) VALUES ('c')
5 INTO t (text) VALUES ('d')
6 SELECT * FROM dual;
4 rows created.
SQL>
SQL> SELECT * FROM t;
ID TEXT
---------- ----------------------
2 Level 1
3 Level 2
4 Level 3
5 Level 4
6 a
6 b
6 c
6 d
8 rows selected.
SQL>
Well, the same would happen even if we don't use an Identity column, and use a sequence explicitly.
SQL> DROP SEQUENCE s;
Sequence dropped.
SQL>
SQL> CREATE SEQUENCE s;
Sequence created.
SQL>
SQL> DROP TABLE t PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE t (
2 ID NUMBER,
3 text VARCHAR2(50),
4 CONSTRAINT id_pk PRIMARY KEY (ID)
5 );
Table created.
SQL>
SQL> INSERT ALL
2 INTO t VALUES (s.nextval, 'a')
3 INTO t VALUES (s.nextval, 'b')
4 INTO t VALUES (s.nextval, 'c')
5 INTO t VALUES (s.nextval, 'd')
6 SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.ID_PK) violated
SQL>
SQL> SELECT * FROM T;
no rows selected
SQL>
SQL> ALTER TABLE t
2 DISABLE CONSTRAINT id_pk;
Table altered.
SQL> INSERT ALL
2 INTO t VALUES (s.nextval, 'a')
3 INTO t VALUES (s.nextval, 'b')
4 INTO t VALUES (s.nextval, 'c')
5 INTO t VALUES (s.nextval, 'd')
6 SELECT * FROM dual;
4 rows created.
SQL> SELECT * FROM T;
ID TEXT
---------- ----------------------------------------
2 a
2 b
2 c
2 d
SQL>
The only possible workaround that come to my mind is, the old method of using a ROW level trigger.
SQL> CREATE OR REPLACE TRIGGER t_trg
2 BEFORE INSERT ON t
3 FOR EACH ROW
4 WHEN (new.id IS NULL)
5 BEGIN
6 SELECT s.NEXTVAL
7 INTO :new.id
8 FROM dual;
9 END;
10 /
Trigger created.
SQL> truncate table t;
Table truncated.
SQL> INSERT ALL
2 INTO t (text) VALUES ('a')
3 INTO t (text) VALUES ('b')
4 INTO t (text) VALUES ('c')
5 INTO t (text) VALUES ('d')
6 SELECT * FROM dual;
4 rows created.
SQL> SELECT * FROM t;
ID TEXT
---------- -------------------------
3 a
4 b
5 c
6 d
SQL>
Regards,
Lalit
|
|
|
|
|
|
|
|
|
|
| Re: Identity column inserts duplicates with Insert All statement, unique constraint violation [message #633365 is a reply to message #633360] |
Tue, 17 February 2015 02:20  |
Lalit Kumar B
Messages: 3174 Registered: May 2013 Location: World Wide on the Web
|
Senior Member |
|
|
I agree with you all, the behavior of the sequence is the way it is designed and documented. It would increment once for an INSERT ALL. My point is, I never cared about this previously using the trigger based approach. It just happened that I was working on Identity columns and all my scripts failed with the unique constraint violation error. Actually I took the Insert All statements from another developer, merged both scripts, my DDL with his DML statements. Now, his DML script is of no use to me I had to split each INSERT ALL statement into individual inserts.
Thanks LF, John and Michel.
|
|
|
|
Goto Forum:
Current Time: Thu Aug 27 02:15:10 CDT 2026
|