This works for me for a mid-sized table.
ALTER TABLE foo ADD ( foo_id integer ) / CREATE SEQUENCE foo_id_seq / CREATE OR REPLACE TRIGGER before_update_foo BEFORE INSERT OR UPDATE ON FOO REFERENCING OLD AS old NEW AS new FOR EACH ROW DECLARE l_foo_id foo.foo_id%TYPE; BEGIN IF :new.foo_id IS NULL THEN SELECT foo_id_seq.nextval INTO l_foo_id FROM dual; :new.foo_id := l_foo_id; END IF; END; / UPDATE foo SET foo_id = NULL / COMMIT / CREATE UNIQUE INDEX foo_ak ON foo( foo_id ) / ALTER TABLE foo MODIFY ( foo_id NOT NULL ) / ALTER TABLE foo ADD (CONSTRAINT foo_ak UNIQUE (foo_id)) /