Как получить текущее значение последовательности оракула, не увеличивая его?

156

Существует ли инструкция SQL для получения значения последовательности, которая не увеличивает его.

Спасибо.

РЕДАКТИРОВАТЬ И ЗАКЛЮЧЕНИЕ

Как утверждает Джастин Кейв, не стоит пытаться «сохранить» порядковый номер так

select a_seq.nextval from dual;

достаточно для проверки значения последовательности.

Я до сих пор считаю ответ Олли хорошим, потому что он ответил на первый вопрос. но спросите себя о необходимости не изменять последовательность, если вы когда-нибудь захотите это сделать.

frno
источник
5
Зачем? Какую проблему вы пытаетесь решить? Если вы используете последовательности правильно, вас никогда не должно волновать, какие значения последовательностей были назначены другим сеансам или какие значения могут быть назначены последующим сеансам.
Джастин Кейв
3
Это проверка после переноса данных, чтобы убедиться, что последовательность была корректно обновлена ​​в соответствии с перенесенными данными
frno
3
Тогда в чем же недостаток простого получения nextvalпоследовательности для проверки? Вы не предполагаете, что последовательности будут без пропусков, верно? Так что «потеря» значения последовательности не должна быть проблемой.
Джастин Кейв
Я думаю, вы правы, я не хотел менять состояние БД для этой проверки, но, честно говоря, я не знаю почему. спасибо за ваше понимание. тем не менее я узнал ваши вещи о последовательности, спасибо всем!
2012 г.
Предполагая, что вы можете надежно получить значение последовательности, каков ваш оракул, против которого вы проверяете, что последовательность была обновлена ​​правильно?
Шеннон Северанс

Ответы:

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

Вы можете получить различные метаданные последовательности из user_sequences, all_sequencesиdba_sequences .

Эти представления работают через сеансы.

РЕДАКТИРОВАТЬ:

Если последовательность находится в вашей схеме по умолчанию, то:

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

Если вы хотите все метаданные, то:

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

Надеюсь, поможет...

EDIT2:

Долгосрочный способ сделать это более надежно, если ваш размер кэша не равен 1, будет:

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.

Просто знайте, что если другие используют последовательность в течение этого времени - они (или вы) могут получить

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

Кроме того, вы можете установить кэш NOCACHEдо сброса, а затем вернуться к его первоначальному значению, чтобы убедиться, что вы не кэшировали много значений.

Олли
источник
Только что попробовал, но у меня нет доступа к таблице 'all_sequence'. Это специальный объект, который вы видите только с правами администратора?
frno
1
ALL_SEQUENCESэто вид. Если у вас нет доступа к нему, попробуйте выбрать, USER_SEQUENCESесли последовательность находится в вашей схеме по умолчанию. (Вам не понадобится sequence_owner = '<sequence_owner>'пункт дляUSER_SEQUENCES ).
Олли
15
Значение LAST_NUMBERin ALL_SEQUENCESне будет последним номером, который фактически был дан сеансу, и не будет номером, который будет возвращен sequence_name.nextvalпри общем вызове . Предполагая, что вы установили последовательность CACHEболее 1 (по умолчанию 20), LAST_NUMBERбудет последним числом в кэше. Нет никакой гарантии, что этот номер когда-либо будет предоставлен какой-либо сессии.
Джастин Кейв
2
ALTER SEQUENCE seq INCREMENT BY -1;будет проблемой, если никто не может гарантировать , что ни один другой сеанс не будет вызываться seq.nextval. В противном случае последовательность будет раздавать повторяющиеся значения, что обычно не то, что нужно.
Шеннон Северанс
1
Оператор сказал: «Это проверка после переноса данных», поэтому не сложно предположить, что БД не используется, но это может быть проблемой, если это не так.
Олли
122

select MY_SEQ_NAME.currval from DUAL;

Имейте в виду, что это работает, только если вы работали select MY_SEQ_NAME.nextval from DUAL;в текущих сеансах.

Ronk
источник
1
Большое спасибо за ваш ответ. Я должен использовать это внутри Boomi и искал решение вверх и вниз
учиться ...
0

Мой первоначальный ответ был фактически неверным, и я рад, что его удалили. Приведенный ниже код будет работать при следующих условиях: а) вы знаете, что никто не изменил последовательность б) последовательность была изменена вашим сеансом. В моем случае я столкнулся с аналогичной проблемой, когда я вызывал процедуру, которая изменила значение, и я уверен, что предположение верно.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

К сожалению, если вы не изменили последовательность в своем сеансе, я считаю, что другие правы, заявив, что NEXTVAL - единственный путь.

georgejo
источник
0

На самом деле это не ответ, и я бы написал его как комментарий, если бы вопрос не был заблокирован. Это отвечает на вопрос:

Зачем тебе это?

Предположим, у вас есть таблица с последовательностью в качестве первичного ключа, и последовательность генерируется триггером вставки. Если вы хотите, чтобы последовательность была доступна для последующих обновлений записи, вам нужен способ извлечь это значение.

Чтобы убедиться, что вы получите правильный вариант, вы можете заключить запрос INSERT и RonK в транзакцию.

Запрос RonK:

select MY_SEQ_NAME.currval from DUAL;

В приведенном выше сценарии предупреждение RonK не применяется, поскольку вставка и обновление будут происходить в одном сеансе.

Эйнсворт
источник
0

Я также попытался использовать CURRVAL, в моем случае, чтобы выяснить, вставил ли какой-то процесс новые строки в какую-либо таблицу с такой последовательностью в качестве Первичного ключа. Я предполагал, что CURRVAL будет самым быстрым методом. Но a) CurrVal не работает, он просто получит старое значение, потому что вы находитесь в другом сеансе Oracle, пока вы не выполните NEXTVAL в своем собственном сеансе. И б) а select max(PK) from TheTableтакже очень быстро, вероятно, потому что ПК всегда индексируется. Илиselect count(*) from TheTable . Я все еще экспериментирую, но оба SELECT кажутся быстрыми.

Я не возражаю против пробела в последовательности, но в моем случае я много думал об опросе, и я бы не хотел представлять себе очень большие пробелы. Особенно, если простой SELECT будет таким же быстрым.

Вывод:

  • CURRVAL довольно бесполезен, поскольку он не обнаруживает NEXTVAL из другого сеанса, он возвращает только то, что вы уже знали из своего предыдущего NEXTVAL
  • SELECT MAX (...) FROM ... является хорошим решением, простым и быстрым, при условии, что ваша последовательность связана с этой таблицей
Roland
источник