Wie kann man den aktuellen Wert einer Orakelsequenz abrufen, ohne ihn zu erhöhen?

156

Gibt es eine SQL-Anweisung, um den Wert einer Sequenz abzurufen, die ihn nicht erhöht?

Vielen Dank.

EDIT UND SCHLUSSFOLGERUNG

Wie von Justin Cave angegeben, ist es nicht sinnvoll, die Sequenznummer so zu "speichern"

select a_seq.nextval from dual;

ist gut genug, um einen Sequenzwert zu überprüfen.

Ich behalte Ollie immer noch als die gute Antwort, weil sie die ursprüngliche Frage beantwortet hat. Fragen Sie sich jedoch nach der Notwendigkeit, die Sequenz nicht zu ändern, wenn Sie dies jemals tun möchten.

frno
quelle
5
Warum? Was ist das Problem, das Sie lösen möchten? Wenn Sie Sequenzen korrekt verwenden, sollte es Ihnen egal sein, welche Sequenzwerte anderen Sitzungen zugewiesen wurden oder welche Werte nachfolgenden Sitzungen zugewiesen werden könnten.
Justin Cave
3
Es ist eine Überprüfung nach der Datenmigration, um sicherzustellen, dass die Sequenz gemäß den migrierten Daten korrekt aktualisiert wurde
am
3
Was ist dann der Nachteil, wenn man einfach nextvaldie Sequenz zum Testen bringt? Sie gehen nicht davon aus, dass Sequenzen lückenlos sind, oder? Das "Verschwenden" eines Sequenzwerts sollte also kein Problem sein.
Justin Cave
Ich denke, Sie haben Recht, ich wollte den Status der Datenbank für diese Überprüfung nicht ändern, aber um ehrlich zu sein, weiß ich nicht warum. Vielen Dank für Ihren Einblick. Trotzdem habe ich deine Sachen über Sequenz gelernt, danke euch allen!
Freitag,
Angenommen, Sie können den Wert einer Sequenz zuverlässig abrufen. Gegen welches Orakel überprüfen Sie, ob die Sequenz ordnungsgemäß aktualisiert wurde?
Shannon Severance

Antworten:

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

Sie können eine Vielzahl von Sequenz Metadaten aus erhalten user_sequences, all_sequencesund dba_sequences.

Diese Ansichten funktionieren sitzungsübergreifend.

BEARBEITEN:

Wenn sich die Sequenz in Ihrem Standardschema befindet, dann:

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

Wenn Sie alle Metadaten möchten, dann:

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

Ich hoffe es hilft...

EDIT2:

Ein langwieriger Weg, dies zuverlässiger zu tun, wenn Ihre Cache-Größe nicht 1 ist, wäre:

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.

Beachten Sie nur, dass andere (Sie) die Sequenz möglicherweise während dieser Zeit verwenden

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

Möglicherweise möchten Sie den Cache auch NOCACHEvor dem Zurücksetzen auf und anschließend auf den ursprünglichen Wert zurücksetzen, um sicherzustellen, dass Sie nicht viele Werte zwischengespeichert haben.

Ollie
quelle
Ich habe es gerade versucht, aber ich habe keinen Zugriff auf eine 'all_sequences'-Tabelle. Ist es ein spezielles Objekt, das Sie nur mit Administratoranmeldeinformationen sehen?
Freitag,
1
ALL_SEQUENCESist eine Ansicht. Wenn Sie keinen Zugriff darauf haben, wählen Sie aus, USER_SEQUENCESob sich die Sequenz in Ihrem Standardschema befindet. (Sie brauchen die sequence_owner = '<sequence_owner>'Klausel nicht für USER_SEQUENCES).
Ollie
15
Das LAST_NUMBERIn ALL_SEQUENCESist nicht die letzte Nummer, die einer Sitzung tatsächlich gegeben wurde, und es ist nicht die Nummer, die von einem Anruf an sequence_name.nextvalim Allgemeinen zurückgegeben wird. Angenommen, Sie haben die Sequenz auf CACHEmehr als 1 festgelegt (der Standardwert ist 20), LAST_NUMBERist dies die letzte Nummer im Cache. Es gibt keine Garantie dafür, dass diese Nummer jemals einer Sitzung zugewiesen wird.
Justin Cave
2
ALTER SEQUENCE seq INCREMENT BY -1;wird ein Problem sein, es sei denn, man kann garantieren , dass keine andere Sitzung anruft seq.nextval. Andernfalls werden in der Sequenz doppelte Werte ausgegeben, was normalerweise nicht der Fall ist.
Shannon Severance
1
Das OP sagte "Es ist eine Überprüfung nach der Datenmigration", daher ist es nicht schwer anzunehmen, dass die Datenbank nicht allgemein verwendet wird, aber es könnte ein Problem sein, wenn dies nicht der Fall wäre.
Ollie
122

select MY_SEQ_NAME.currval from DUAL;

Beachten Sie, dass dies nur funktioniert, wenn Sie select MY_SEQ_NAME.nextval from DUAL;in den aktuellen Sitzungen ausgeführt haben.

RonK
quelle
1
Vielen Dank für Ihre Antwort. Ich muss dies in Boomi verwenden und suchte nach einer Lösung für das Auf und Ab
Lernen ...
0

Meine ursprüngliche Antwort war sachlich falsch und ich bin froh, dass sie entfernt wurde. Der folgende Code funktioniert unter den folgenden Bedingungen: a) Sie wissen, dass niemand anderes die Sequenz geändert hat. B) Die Sequenz wurde von Ihrer Sitzung geändert. In meinem Fall ist ein ähnliches Problem aufgetreten, bei dem ich eine Prozedur aufgerufen habe, die einen Wert geändert hat, und ich bin zuversichtlich, dass die Annahme wahr ist.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

Wenn Sie die Reihenfolge in Ihrer Sitzung nicht geändert haben, sind andere leider der Meinung, dass NEXTVAL der einzige Weg ist.

Georgejo
quelle
0

Dies ist wirklich keine Antwort und ich hätte sie als Kommentar eingegeben, wenn die Frage nicht gesperrt worden wäre. Dies beantwortet die Frage:

Warum willst du es?

Angenommen, Sie haben eine Tabelle mit der Sequenz als Primärschlüssel und die Sequenz wird von einem Insert-Trigger generiert. Wenn Sie die Sequenz für nachfolgende Aktualisierungen des Datensatzes verfügbar haben möchten, müssen Sie eine Möglichkeit haben, diesen Wert zu extrahieren.

Um sicherzustellen, dass Sie die richtige erhalten, möchten Sie möglicherweise die INSERT- und RonK-Abfrage in eine Transaktion einschließen.

RonKs Frage:

select MY_SEQ_NAME.currval from DUAL;

Im obigen Szenario gilt die Einschränkung von RonK nicht, da das Einfügen und Aktualisieren in derselben Sitzung erfolgen würde.

Ainsworth
quelle
0

Ich habe auch versucht, CURRVAL zu verwenden, um herauszufinden, ob ein Prozess neue Zeilen in eine Tabelle mit dieser Sequenz als Primärschlüssel eingefügt hat. Ich ging davon aus, dass CURRVAL die schnellste Methode sein würde. Aber a) CurrVal funktioniert nicht, es erhält nur den alten Wert, weil Sie sich in einer anderen Oracle-Sitzung befinden, bis Sie in Ihrer eigenen Sitzung ein NEXTVAL durchführen. Und b) a select max(PK) from TheTableist auch sehr schnell, wahrscheinlich weil eine PK immer indiziert ist. Oder select count(*) from TheTable. Ich experimentiere immer noch, aber beide SELECTs scheinen schnell zu sein.

Ich habe nichts gegen eine Lücke in einer Sequenz, aber in meinem Fall habe ich darüber nachgedacht, viel abzufragen, und ich würde die Idee sehr großer Lücken hassen. Besonders wenn ein einfaches SELECT genauso schnell wäre.

Fazit:

  • CURRVAL ist ziemlich nutzlos, da es NEXTVAL nicht aus einer anderen Sitzung erkennt, sondern nur das zurückgibt, was Sie bereits von Ihrem vorherigen NEXTVAL gewusst haben
  • SELECT MAX (...) FROM ... ist eine gute Lösung, einfach und schnell, vorausgesetzt, Ihre Sequenz ist mit dieser Tabelle verknüpft
Roland
quelle