Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como faço para redefinir automaticamente o valor de uma sequência para 0 todos os anos no Oracle 10g?


As sequências não são realmente projetadas para serem redefinidas. Mas há alguns casos em que é desejável redefinir uma sequência, por exemplo, ao configurar dados de teste ou mesclar dados de produção de volta em um ambiente de teste. Este tipo de atividade não normalmente feito na produção.

SE esse tipo de operação for colocado em produção, ele precisa ser testado exaustivamente. (O que mais preocupa é a possibilidade de o procedimento de reinicialização ser realizado acidentalmente na hora errada, como no meio do ano.

Soltar e recriar a sequência é uma abordagem. Como uma operação, é bastante simples no que diz respeito à SEQUÊNCIA:
    DROP SEQUENCE MY_SEQ;
    CREATE SEQUENCE MY_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 0;

[EDIT] Como Matthew Watson corretamente aponta, cada instrução DDL (como DROP, CREATE, ALTER) causará um commit implícito. [/EDITAR]

Mas, quaisquer privilégios concedidos na SEQUENCE serão descartados, portanto, eles precisarão ser concedidos novamente. Quaisquer objetos que façam referência à sequência serão invalidados. Para obter isso mais generalizado, você precisaria salvar privilégios (antes de descartar a sequência) e depois concedê-los novamente.

Uma segunda abordagem é ALTERAR uma SEQUENCE existente, sem descartar e recriá-la. A redefinição da sequência pode ser feita alterando o valor INCREMENT para um valor negativo (a diferença entre o valor atual e 0) e, em seguida, faça exatamente um .NEXTVAL para definir o valor atual como 0 e, em seguida, altere o INCREMENT de volta para 1. Eu usei essa mesma abordagem antes (manualmente, em um ambiente de teste), para definir uma sequência para um valor maior também.

É claro que, para que isso funcione corretamente, você precisa segurar nenhuma outra sessão faz referência à sequência enquanto esta operação está sendo executada. Um .NEXTVAL extra no instante errado estragará o reset. (OBSERVAÇÃO:conseguir isso no lado do banco de dados será difícil, se o aplicativo estiver se conectando como o proprietário da sequência, em vez de um usuário separado.)

Para que isso aconteça todos os anos, você precisa agendar um trabalho. A redefinição da sequência terá que ser coordenada com a redefinição da parte YYYY do seu identificador.

Aqui está um exemplo:

http://www.jaredstill.com/content/reset-sequence.html

[EDITAR]

NÃO TESTADO espaço reservado para um possível design de um bloco PL/SQL para redefinir a sequência
    declare
      pragma autonomous_transaction;
      ln_increment       number;
      ln_curr_val        number;
      ln_reset_increment number;
      ln_reset_val       number;
    begin

      -- save the current INCREMENT value for the sequence
      select increment_by
        into ln_increment
        from user_sequences
       where sequence_name = 'MY_SEQ';

      -- determine the increment value required to reset the sequence
      -- from the next fetched value to 0
      select -1 - MY_SEQ.nextval into ln_reset_increment from dual;

      -- fetch the next value (to make it the current value)
      select MY_SEQ.nextval into ln_curr from dual;

      -- change the increment value of the sequence to 
      EXECUTE IMMEDIATE 'alter sequence MY_SEQ increment by '
        || ln_reset_increment ||' minvalue 0';

      -- advance the sequence to set it to 0
      select MY_SEQ.nextval into ln_reset_val from dual;

      -- set increment back to the previous(ly saved) value
      EXECUTE IMMEDIATE 'alter sequence MY_SEQ increment by '
        || ln_increment ;
    end;
    /

NOTAS:
  • como proteger melhor a sequência do acesso enquanto ela está sendo redefinida, RENOMEAR?
  • Vários casos de teste para trabalhar aqui.
  • Primeira passagem, verifique os casos normativos de sequência positiva, ascendente, de incremento 1.
  • uma abordagem melhor seria criar uma nova SEQUÊNCIA, adicionar permissões, renomear sequências novas e existentes e, em seguida, recompilar as dependências?