Як отримати поточне значення послідовності oracle, не збільшуючи його?


156

Чи є інструкція SQL для отримання значення послідовності, яка не збільшує її.

Дякую.

РЕДАКТУВАННЯ І ВИСНОВОК

Як заявив Джастін Кейв, не корисно намагатися так "зберегти" порядковий номер

select a_seq.nextval from dual;

достатньо хороший, щоб перевірити значення послідовності.

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


5
Чому? Яку проблему ви намагаєтеся вирішити? Якщо ви правильно використовуєте послідовності, вам ніколи не важливо, які значення послідовностей були призначені іншим сеансам або які значення можуть бути призначені наступним сеансам.
Джастін Печера

3
Це перевірка після міграції даних, щоб переконатися, що послідовність було оновлено правильно відповідно до міграції даних
frno

3
Тоді в чому полягає недолік просто отримати nextvalпослідовність для тестування? Ви не припускаєте, що послідовності будуть без проміжків, правда? Тож "витрачати" значення послідовності не повинно бути проблемою.
Джастін Печера

Я думаю, ти маєш рацію, я не хотів змінити стан db для цієї перевірки, але якщо чесно, я не знаю чому. дякую за ваше розуміння. все ж я дізнався ваші речі про послідовність, дякую всім!
frno

Припускаючи, що ви можете надійно отримати значення послідовності, який ваш оракул, щодо якого ви перевіряєте, чи послідовність оновлена ​​належним чином?
Шеннон Северанс

Відповіді:


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скидання, а потім повернути його до початкового значення, щоб переконатися, що ви не кешували багато значень.


Просто спробував це, але у мене немає доступу до таблиці "всі_послідки". Це спеціальний об’єкт, який ви бачите лише з обліковими записами адміністратора?
frno

1
ALL_SEQUENCESце вид. Якщо у вас немає доступу до нього, спробуйте вибрати, USER_SEQUENCESчи є послідовність у вашій схемі за замовчуванням. ( sequence_owner = '<sequence_owner>'Стаття для цього вам не знадобиться USER_SEQUENCES).
Оллі

15
LAST_NUMBERВ 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;на поточних сесіях.


1
Дякую купу за вашу відповідь. Я повинен використовувати це всередині Boomi і шукав рішення вгору і вниз
навчання ...

0

Моя оригінальна відповідь фактично була неправильною, і я радий, що її видалили. Нижче наведений код працюватиме за таких умов: а) ви знаєте, що ніхто більше не змінював послідовність; б) послідовність була змінена вашим сеансом. У моєму випадку я зіткнувся з подібною проблемою, коли я викликав процедуру, яка змінила значення, і я впевнений, що припущення є правдивим.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

На жаль, якщо ви не змінили послідовність свого сеансу, я вважаю, що інші вірно заявляють, що NEXTVAL - це єдиний шлях.


0

Це справді не відповідь, і я би вписав це як коментар, якби питання не було заблоковано. Це відповідає на питання:

Чому б ти цього хотів?

Припустимо, у вас є таблиця з послідовністю в якості основного ключа, і послідовність створюється тригером вставки. Якщо ви хочете мати доступну послідовність для наступних оновлень запису, вам потрібно мати спосіб витягти це значення.

Для того, щоб переконатися, що ви отримали потрібний, ви можете загорнути запит INSERT та RonK в транзакцію.

Запит RonK:

select MY_SEQ_NAME.currval from DUAL;

У вищенаведеному сценарії застереження RonK не застосовується, оскільки вставка та оновлення відбуватимуться в одному сеансі.


0

Я також намагався використовувати CURRVAL, в моєму випадку, щоб дізнатися, чи якийсь процес вставив нові рядки в якусь таблицю з такою послідовністю як Первинний ключ. Моє припущення було, що CURRVAL буде найшвидшим методом. Але а) CurrVal не працює, він просто отримає старе значення, тому що ви перебуваєте в іншому сеансі Oracle, поки ви не зробите NEXTVAL у своєму сеансі. І b) a select max(PK) from TheTableтакож дуже швидко, ймовірно, тому, що ПК завжди індексується. Або select count(*) from TheTable. Я все ще експериментую, але обидва SELECT здаються швидкими.

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

Висновок:

  • CURRVAL є досить марним, оскільки він не виявляє NEXTVAL з іншого сеансу, він повертає лише те, що ви вже знали з попереднього NEXTVAL
  • SELECT MAX (...) FROM ... - це хороше рішення, просте та швидке, якщо ваша послідовність пов'язана з цією таблицею
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.