Como recuperar o valor atual de uma sequência oracle sem incrementá-lo?


156

Existe uma instrução SQL para recuperar o valor de uma sequência que não a incrementa.

Obrigado.

EDIÇÃO E CONCLUSÃO

Conforme declarado por Justin Cave Não é útil tentar "salvar" o número da sequência para

select a_seq.nextval from dual;

é bom o suficiente para verificar um valor de sequência.

Ainda mantenho a resposta de Ollie como boa porque ela respondeu à pergunta inicial. mas pergunte a si mesmo sobre a necessidade de não modificar a sequência, se você quiser fazê-lo.


5
Por quê? Qual é o problema que você está tentando resolver? Se você estiver usando sequências corretamente, nunca se preocupe com os valores de sequência atribuídos a outras sessões ou com os valores que podem ser atribuídos às sessões subseqüentes.
— Justin Caverna

3
É uma verificação após a migração de dados para ter certeza da sequência foram atualizados corretamente de acordo com os dados migrados
— frno

3
Então, qual é a desvantagem de simplesmente nextvaltestar a sequência? Você não está assumindo que as sequências serão livres de falhas, certo? Portanto, "desperdiçar" um valor de sequência não deve ser um problema.
— 11557 Justin Bieber

Acho que você está certo, não queria mudar o estado do banco de dados para essa verificação, mas, para ser sincero, não sei por que. obrigado pela sua compreensão. no entanto, eu aprendi suas coisas sobre sequência, obrigado a todos!
— frno

Supondo que você possa obter com segurança o valor de uma sequência, qual é o seu oráculo contra o qual você está verificando se a sequência foi atualizada corretamente?
— 21603 Shannon Severance

Respostas:


173
SELECT last_number
  FROM all_sequences
 WHERE sequence_owner = '<sequence owner>'
   AND sequence_name = '<sequence_name>';

Você pode obter vários metadados de sequência de user_sequences, all_sequencese dba_sequences.

Essas visualizações funcionam em todas as sessões.

EDITAR:

Se a sequência estiver no seu esquema padrão, então:

SELECT last_number
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

Se você deseja todos os metadados, então:

SELECT *
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

Espero que ajude...

EDIT2:

Uma maneira prolongada de fazê-lo de maneira mais confiável se o tamanho do cache não for 1 seria:

SELECT increment_by I
  FROM user_sequences
 WHERE sequence_name = 'SEQ';

      I
-------
      1

SELECT seq.nextval S
  FROM dual;

      S
-------
   1234

-- Set the sequence to decrement by 
-- the same as its original increment
ALTER SEQUENCE seq 
INCREMENT BY -1;

Sequence altered.

SELECT seq.nextval S
  FROM dual;

      S
-------
   1233

-- Reset the sequence to its original increment
ALTER SEQUENCE seq 
INCREMENT BY 1;

Sequence altered.

Apenas tome cuidado para que, se outras pessoas estiverem usando a sequência durante esse período - elas (ou você)

ORA-08004: sequence SEQ.NEXTVAL goes below the sequences MINVALUE and cannot be instantiated

Além disso, convém definir o cache como NOCACHEanterior à redefinição e depois retornar ao seu valor original posteriormente para garantir que você não tenha armazenado muitos valores em cache.


Apenas tentei, mas não tenho acesso a uma tabela 'all_sequences'. É um objeto especial que você vê apenas com credenciais de administrador?
— frno

1
ALL_SEQUENCESé uma visão. Se você não tiver acesso a ele, tente selecionar USER_SEQUENCESse a sequência está no seu esquema padrão. (Você não precisará da sequence_owner = '<sequence_owner>'cláusula para USER_SEQUENCES).
— Ollie

15
O LAST_NUMBERin ALL_SEQUENCESnão será o último número que uma sessão foi realmente fornecida e não será o número que seria retornado de uma chamada para sequence_name.nextvalem geral. Supondo que você configurou a sequência para CACHEmais de 1 (o padrão é 20), LAST_NUMBERserá o último número que está no cache. Não há garantia de que esse número seja realmente fornecido a qualquer sessão.
— Justin Caverna

2
ALTER SEQUENCE seq INCREMENT BY -1;será um problema, a menos que se possa garantir que nenhuma outra sessão será chamada seq.nextval. Caso contrário, a sequência estará distribuindo valores duplicados, o que geralmente não é o que se deseja.
— Shannon Severance

1
O OP disse "É uma verificação após a migração de dados", portanto, não é exagero supor que o banco de dados não esteja em uso geral, mas pode ser um problema se esse não for o caso.
— Ollie

122

select MY_SEQ_NAME.currval from DUAL;

Lembre-se de que só funciona se você executou select MY_SEQ_NAME.nextval from DUAL;nas sessões atuais.


1
Muito obrigado pela sua resposta. Eu tenho que usar isso dentro Boomi e estava à procura de uma solução para cima e para baixo
— aprendizagem ...

0

Minha resposta original estava incorreta e estou feliz por ter sido removida. O código abaixo funcionará nas seguintes condições: a) você sabe que ninguém mais modificou a sequência; b) a sequência foi modificada pela sua sessão. No meu caso, encontrei um problema semelhante no qual estava chamando um procedimento que modifica um valor e estou confiante de que a suposição é verdadeira.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

Infelizmente, se você não modificou a sequência em sua sessão, acredito que outras pessoas estejam corretas ao afirmar que o NEXTVAL é o único caminho a percorrer.


0

Esta não é uma resposta, na verdade e eu a teria inserido como um comentário se a pergunta não tivesse sido bloqueada. Isso responde à pergunta:

Porque você deveria querer isso?

Suponha que você tenha uma tabela com a sequência como chave primária e a sequência seja gerada por um gatilho de inserção. Se você quiser ter a sequência disponível para atualizações subseqüentes no registro, precisará de uma maneira de extrair esse valor.

Para garantir que você obtenha a correta, você pode agrupar a consulta INSERT e RonK em uma transação.

Consulta de RonK:

select MY_SEQ_NAME.currval from DUAL;

No cenário acima, a ressalva de RonK não se aplica, pois a inserção e a atualização aconteceriam na mesma sessão.


0

Também tentei usar CURRVAL, no meu caso, para descobrir se algum processo inseriu novas linhas em alguma tabela com essa sequência como Chave Primária. Minha suposição era que CURRVAL seria o método mais rápido. Mas a) CurrVal não funciona, ele apenas obterá o valor antigo porque você está em outra sessão do Oracle, até fazer um NEXTVAL em sua própria sessão. E b) a select max(PK) from TheTabletambém é muito rápido, provavelmente porque uma PK é sempre indexada. Ouselect count(*) from TheTable . Ainda estou experimentando, mas os dois SELECTs parecem rápidos.

Não me importo com uma lacuna na sequência, mas no meu caso eu estava pensando muito em pesquisar, e odiaria a ideia de lacunas muito grandes. Especialmente se um simples SELECT fosse tão rápido.

Conclusão:

  • CURRVAL é bastante inútil, pois não detecta o NEXTVAL de outra sessão, apenas retorna o que você já sabia do seu NEXTVAL anterior
  • SELECT MAX (...) FROM ... é uma boa solução, simples e rápida, supondo que sua sequência esteja vinculada a essa tabela
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.