Advertisement Space

Generating unique IDs in Oracle

Unlike MySQL's AUTO_INCREMENT, Oracle has traditionally used sequences — independent database objects that generate unique numbers. Since 12c, there's also an identity column option.

Recipe #1 - Creating and using a sequence

CREATE SEQUENCE emp_seq
  START WITH 1000
  INCREMENT BY 1
  NOCACHE
  NOCYCLE;

Use it in an INSERT:

INSERT INTO emp (empno, ename, sal)
VALUES (emp_seq.NEXTVAL, 'NEW_EMP', 3000);

Get the current value (only works after calling NEXTVAL in the same session):

SELECT emp_seq.CURRVAL FROM DUAL;

Recipe #2 - Auto-populate IDs with a trigger (pre-12c)

Before Oracle 12c, the standard pattern was to use a trigger:

CREATE OR REPLACE TRIGGER emp_bi_trg
  BEFORE INSERT ON emp
  FOR EACH ROW
BEGIN
  IF :NEW.empno IS NULL THEN
    :NEW.empno := emp_seq.NEXTVAL;
  END IF;
END;

Now you can insert without specifying the ID:

INSERT INTO emp (ename, sal) VALUES ('SMITH', 2000);

Recipe #3 - Identity columns (Oracle 12c+)

Oracle 12c introduced identity columns — the modern way to auto-generate IDs:

CREATE TABLE new_employees (
  id     NUMBER GENERATED ALWAYS AS IDENTITY,
  name   VARCHAR2(100) NOT NULL,
  salary NUMBER
);

Options for identity columns:

CREATE TABLE orders (
  order_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY
    (START WITH 10000 INCREMENT BY 1),
  customer VARCHAR2(100),
  amount   NUMBER
);

Recipe #4 - Useful sequence queries

Check all sequences and their current state:

SELECT sequence_name, min_value, max_value,
       increment_by, last_number, cache_size
FROM user_sequences
ORDER BY sequence_name;

Reset a sequence (Oracle 18c+):

ALTER SEQUENCE emp_seq RESTART START WITH 1;

For pre-18c, you have to drop and recreate, or use the increment trick:

-- Get current value, then set negative increment
ALTER SEQUENCE emp_seq INCREMENT BY -999;
SELECT emp_seq.NEXTVAL FROM DUAL;
ALTER SEQUENCE emp_seq INCREMENT BY 1;