sql >> Base de Datos >  >> RDS >> Oracle

Necesita restablecer el valor de la secuencia en Oracle

Razones por las que no debe restablecer el valor si se está utilizando:

¿Qué sucede si tiene 20 registros y elimina los registros 5-10? Tiene un espacio en el medio que restablecer la secuencia no resolverá. Las secuencias nunca generar una secuencia de números sin huecos, un 1, 2 .. n perfecto .

Si llama a .nextval y no use el valor que ha desaparecido . ¿Vas a soltar y volver a crear la secuencia? Si inicia una inserción y la cancela y Oracle revierte lo que ha hecho, esos valores desaparecieron . Si configura nocache entonces tendrá menos brechas pero a costa de un impacto en el rendimiento; ¿vale la pena?

Su caché debe establecerse en la cantidad de inserciones que espera hacer en cualquier momento en todas las sesiones para evitar cualquier problema de rendimiento. Las secuencias están diseñadas para proporcionar una forma muy rápida y escalable de crear una clave sustituta sin bloqueos, etc. no para volver a generar el conjunto de enteros positivos.

Al final del día no debería importar en lo más mínimo. Si confía en una secuencia ininterrumpida como la clave de su tabla, entonces tiene un problema con sus datos en lugar de con las secuencias.

Respondiendo a la pregunta:

Para responder realmente a su pregunta, necesitaría:

  1. En primer lugar, averigüe cuál es el valor máximo de id (secuencia) en su tabla.
  2. Luego suelte y vuelva a crear la secuencia.

Encontrar el valor máximo significa que necesitaría volver a crear la secuencia dinámicamente a costa de otro impacto en el rendimiento.

Si intenta insertar algo en su tabla mientras esto sucede, fallará y puede invalidar cualquier disparador u otros objetos que usen la secuencia:

declare

   l_max_value number;

begin

   select max(id)
     into l_max_value
     from my_table;

   execute immediate 'drop sequence my_sequence_name';

   -- nocache is not recommended if you are inserting more than
   -- one row at a time, or inserting with any speed at all.
   execute immediate 'create sequence my_sequence_name
                           start with ' || l_max_value
                      || ' increment by 1
                           nomaxvalue
                           nocycle
                           nocache';

end;
/

Como digo, esto no se recomienda y simplemente debe ignorar cualquier brecha.

Actualización:también conocida como Una respuesta mejor gracias a Jeffrey Kemp:

Contrariamente a la recomendación de la documentación, como sugirió Jeffrey Kemp en los comentarios, hay una manera de hacer esto sin soltar y volver a crear la secuencia.

A saber, por:

  1. Calcular la diferencia entre el id máximo en su tabla y el valor actual de la secuencia.
  2. Alterando la secuencia para incrementar por este número negativo
  3. Alterando la secuencia para incrementar en 1 nuevamente.

Los beneficios de esto son que el objeto aún existe, y los activadores, las concesiones, etc. aún se mantienen. La desventaja, como yo lo veo, es que si otra sesión aumenta en este número negativo al mismo tiempo que la tuya, puedes retroceder demasiado.

Aquí hay una demostración:

Configurar la prueba:

SQL> create sequence test_seq
  2   start with 1
  3   increment by 1
  4   nomaxvalue
  5   nocycle
  6   nocache;

Sequence created.

SQL>
SQL> create table tmp_test ( id number(16) );

Table created.

SQL>
SQL> declare
  2     l_nextval number;
  3  begin
  4
  5    for i in 1 .. 20 loop
  6       insert into tmp_test values ( test_seq.nextval );
  7    end loop;
  8
  9  end;
 10  /

PL/SQL procedure successfully completed.

SQL>
SQL> select test_seq.currval from dual;

   CURRVAL
----------
        20

SQL>
SQL> delete from tmp_test where id > 15;

5 rows deleted.

SQL> commit;

Commit complete.

Revertir la secuencia

SQL>
SQL> declare
  2
  3     l_max_id number;
  4     l_max_seq number;
  5
  6  begin
  7
  8     -- Get the maximum ID
  9     select max(id) into l_max_id
 10       from tmp_test;
 11
 12     -- Get the current sequence value;
 13     select test_seq.currval into l_max_seq
 14       from dual;
 15
 16     -- Alter the sequence to increment by the difference ( -5 in this case )
.
 17     execute immediate 'alter sequence test_seq
 18                          increment by ' || ( l_max_id - l_max_seq );
 19
 20     -- 'increment' by -5
 21     select test_seq.nextval into l_max_seq
 22       from dual;
 23
 24     -- Change the sequence back to normal
 25     execute immediate 'alter sequence test_seq
 26                          increment by 1';
 27
 28  end;
 29  /

PL/SQL procedure successfully completed.

SQL>
SQL> select test_seq.currval from dual;

   CURRVAL
----------
        15

SQL>