Incrementing Oracle Sequences Without Permissions

If you are ever working with a database where data is consistently being imported, dropped, and/or restored; sooner or later you will find yourself in the situation where the primary key of a table is no longer synchronized with the sequence used to generate it.

If you have the appropriate permissions, this is easy to fix. Say you need to advance the sequence by 500, you just execute the following sql:

ALTER sequence MY_SEQ increment BY 500;
SELECT MY_SEQ.NEXTVAL FROM dual;
ALTER sequence MY_SEQ increment BY 1;

What do you do if you don’t have the correct permissions to do this? You can always call up the dba and ask him. If you’re impatient, you can also do a little pl/sql programming to accomplish the same thing. All you want to do is just repeatedly select the next value until the sequence value is higher that the current key value.

DECLARE
  current_value NUMBER;
  seq_val NUMBER;
BEGIN
  SELECT MAX(MY_TABLE.id) INTO current_val FROM MY_TABLE;
  WHILE current_val >= seq_val
  LOOP
    SELECT MY_SEQ.NEXTVAL INTO seq_val FROM dual;
  END LOOP;
END;

Of course, if you encounter this situation once, chances are that you will encounter it many times. Next, you can create a function that takes the table name, key column name, and sequence name and then executes dynamically created sql to fix the problem.

CREATE OR REPLACE PROCEDURE INCREMENT_SEQ(IN TABLE_NAME, IN ID_COLUMN_NAME, IN SEQUENCE_NAME) IS
DECLARE
  current_value NUMBER;
  seq_val NUMBER := -1;
BEGIN
  EXECUTE IMMEDIATE 'select max(' || TABLE_NAME || '.' || ID_COLUMN_NAME || ') into current value from ' || TABLE_NAME;
  WHILE current_val >= seq_val
  LOOP
    EXECUTE IMMEDIATE 'select ' || SEQUENCE_NAME || ".nextval into seq_val from dual';
  end loop;
END INCREMENT_SEQ;

Now, you should be able to fix any sequence/key mismatches simply by calling the procedure.

INCREMENT_SEQ('MY_TABLE', 'ID', 'MY_SEQ');

One comment

Comments are closed.