Comment récupérer la valeur actuelle d'une séquence oracle sans l'incrémenter?

156

Existe-t-il une instruction SQL pour récupérer la valeur d'une séquence qui ne l'incrémente pas.

Merci.

MODIFIER ET CONCLUSION

Comme indiqué par Justin Cave Il n'est pas utile d'essayer de "sauvegarder" le numéro de séquence afin

select a_seq.nextval from dual;

est assez bon pour vérifier une valeur de séquence.

Je garde toujours la réponse d'Ollie comme la bonne parce qu'elle a répondu à la question initiale. mais interrogez-vous sur la nécessité de ne pas modifier la séquence si jamais vous voulez le faire.

frno
la source
5
Pourquoi? Quel est le problème que vous essayez de résoudre? Si vous utilisez correctement les séquences, vous ne devriez jamais vous soucier des valeurs de séquence qui ont été attribuées à d'autres sessions ou des valeurs qui pourraient être attribuées aux sessions suivantes.
Justin Cave
3
C'est un contrôle après la migration des données pour être sûr que la séquence a été mise à jour correctement en fonction des données migrées
frno
3
Alors, quel est l'inconvénient de simplement faire nextvaltester la séquence? Vous ne supposez pas que les séquences seront sans lacunes, non? Donc "gaspiller" une valeur de séquence ne devrait pas être un problème.
Justin Cave
Je suppose que vous avez raison, je ne voulais pas changer l'état de la base de données pour ce contrôle, mais pour être honnête, je ne sais pas pourquoi. merci pour votre perspicacité. néanmoins j'ai appris vos trucs sur la séquence, merci à tous!
frno
En supposant que vous puissiez obtenir de manière fiable la valeur d'une séquence, quel est votre oracle par rapport auquel vous vérifiez que la séquence a été mise à jour correctement?
Shannon Severance

Réponses:

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

Vous pouvez obtenir une variété de métadonnées de séquence à partir de user_sequences, all_sequenceset dba_sequences.

Ces vues fonctionnent à travers les sessions.

ÉDITER:

Si la séquence est dans votre schéma par défaut, alors:

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

Si vous voulez toutes les métadonnées, alors:

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

J'espère que ça aide...

EDIT2:

Une façon longue et fastidieuse de le faire de manière plus fiable si la taille de votre cache n'est pas de 1 serait:

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.

Sachez simplement que si d'autres utilisent la séquence pendant ce temps, ils (ou vous) peuvent

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

En outre, vous pouvez définir le cache sur NOCACHEavant la réinitialisation, puis revenir à sa valeur d'origine par la suite pour vous assurer que vous n'avez pas mis en cache beaucoup de valeurs.

Ollie
la source
Je viens de l'essayer mais je n'ai pas accès à une table 'all_sequences'. S'agit-il d'un objet spécial que vous ne voyez qu'avec les informations d'identification d'administrateur?
frno
1
ALL_SEQUENCESest une vue. Si vous n'y avez pas accès, essayez de sélectionner USER_SEQUENCESsi la séquence est dans votre schéma par défaut. (Vous n'aurez pas besoin de la sequence_owner = '<sequence_owner>'clause pour USER_SEQUENCES).
Ollie
15
Le LAST_NUMBERdans ALL_SEQUENCESne sera pas le dernier numéro une session a été effectivement donnée et ne sera pas le nombre qui serait retourné d'un appel à sequence_name.nextvalen général. En supposant que vous ayez défini la séquence sur CACHEplus de 1 (la valeur par défaut est 20), LAST_NUMBERsera le dernier numéro qui se trouve dans le cache. Il n'y a aucune garantie que ce numéro sera jamais donné à une session.
Justin Cave
2
ALTER SEQUENCE seq INCREMENT BY -1;va être un problème à moins que l'on puisse garantir qu'aucune autre session n'appellera seq.nextval. Sinon, la séquence distribuera des valeurs en double, ce qui n'est généralement pas ce que l'on veut.
Shannon Severance
1
L'OP a dit "C'est une vérification après la migration des données", donc il n'est pas exagéré de supposer que la base de données n'est pas utilisée en général, mais cela pourrait poser un problème si ce n'était pas le cas.
Ollie
122

select MY_SEQ_NAME.currval from DUAL;

Gardez à l'esprit que cela ne fonctionne que si vous avez exécuté select MY_SEQ_NAME.nextval from DUAL;les sessions en cours.

RonK
la source
1
Merci beaucoup pour votre réponse. Je dois utiliser cela dans Boomi et je cherchais une solution de haut en bas
apprentissage ...
0

Ma réponse initiale était factuellement incorrecte et je suis heureux qu'elle ait été supprimée. Le code ci-dessous fonctionnera dans les conditions suivantes a) vous savez que personne d'autre n'a modifié la séquence b) la séquence a été modifiée par votre session. Dans mon cas, j'ai rencontré un problème similaire où j'appelais une procédure qui modifiait une valeur et je suis convaincu que l'hypothèse est vraie.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

Malheureusement, si vous n'avez pas modifié la séquence dans votre session, je pense que d'autres ont raison de dire que NEXTVAL est la seule façon de procéder.

Georgejo
la source
0

Ce n'est pas vraiment une réponse et je l'aurais saisie comme commentaire si la question n'avait pas été verrouillée. Cela répond à la question:

Pourquoi le voudrais-tu?

Supposons que vous ayez une table avec la séquence comme clé primaire et la séquence est générée par un déclencheur d'insertion. Si vous souhaitez que la séquence soit disponible pour les mises à jour ultérieures de l'enregistrement, vous devez disposer d'un moyen d'extraire cette valeur.

Afin de vous assurer que vous obtenez le bon, vous voudrez peut-être envelopper la requête INSERT et RonK dans une transaction.

Requête de RonK:

select MY_SEQ_NAME.currval from DUAL;

Dans le scénario ci-dessus, la mise en garde de RonK ne s'applique pas car l'insertion et la mise à jour se produiraient dans la même session.

Ainsworth
la source
0

J'ai également essayé d'utiliser CURRVAL, dans mon cas pour savoir si un processus insérait de nouvelles lignes dans une table avec cette séquence comme clé primaire. Mon hypothèse était que CURRVAL serait la méthode la plus rapide. Mais a) CurrVal ne fonctionne pas, il récupérera simplement l'ancienne valeur parce que vous êtes dans une autre session Oracle, jusqu'à ce que vous fassiez un NEXTVAL dans votre propre session. Et b) a select max(PK) from TheTableest également très rapide, probablement parce qu'un PK est toujours indexé. Ou select count(*) from TheTable. J'expérimente toujours, mais les deux SELECT semblent rapides.

Cela ne me dérange pas une interruption dans une séquence, mais dans mon cas, je pensais beaucoup aux sondages, et je détesterais l'idée de très grandes lacunes. Surtout si un simple SELECT serait tout aussi rapide.

Conclusion:

  • CURRVAL est assez inutile, car il ne détecte pas NEXTVAL d'une autre session, il ne renvoie que ce que vous saviez déjà de votre NEXTVAL précédent
  • SELECT MAX (...) FROM ... est une bonne solution, simple et rapide, en supposant que votre séquence est liée à cette table
Roland
la source