Bagaimana cara mengambil nilai saat ini dari urutan oracle tanpa menambahkannya?

156

Apakah ada instruksi SQL untuk mengambil nilai urutan yang tidak menambahnya.

Terima kasih.

EDIT DAN KESIMPULAN

Seperti yang dikatakan oleh Justin Cave Tidak berguna untuk mencoba "menyimpan" nomor urut begitu

select a_seq.nextval from dual;

cukup baik untuk memeriksa nilai urutan.

Saya masih menyimpan jawaban Ollie sebagai jawaban yang baik karena menjawab pertanyaan awal. tetapi tanyakan pada diri Anda tentang perlunya tidak mengubah urutan jika Anda pernah ingin melakukannya.

frno
sumber
5
Mengapa? Apa masalah yang Anda coba selesaikan? Jika Anda menggunakan urutan dengan benar, Anda tidak boleh peduli nilai urutan apa yang telah ditetapkan untuk sesi lain atau nilai apa yang mungkin ditugaskan untuk sesi berikutnya.
Justin Cave
3
Ini adalah pemeriksaan setelah migrasi data untuk memastikan urutan telah diperbarui dengan benar sesuai dengan data yang dimigrasikan
frno
3
Lalu apa downside untuk hanya mendapatkan nextvalurutan untuk menguji itu? Anda tidak berasumsi bahwa urutannya akan bebas celah, bukan? Jadi "membuang-buang" nilai urutan seharusnya tidak menjadi masalah.
Justin Cave
Saya kira Anda benar, saya tidak ingin mengubah status db untuk cek itu tetapi jujur ​​saya tidak tahu mengapa. terima kasih atas wawasan anda. Meskipun demikian saya memang mempelajari hal-hal Anda tentang urutan, terima kasih semua!
frno
Dengan asumsi Anda dapat dengan andal mendapatkan nilai suatu urutan, apa ramalan Anda terhadap yang Anda periksa bahwa urutan telah diperbarui dengan benar?
Shannon Severance

Jawaban:

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

Anda bisa mendapatkan berbagai metadata urutan dari user_sequences, all_sequencesdan dba_sequences.

Pandangan ini bekerja lintas sesi.

EDIT:

Jika urutannya dalam skema default Anda, maka:

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

Jika Anda menginginkan semua metadata, maka:

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

Semoga ini bisa membantu ...

EDIT2:

Cara bertele-tele untuk melakukannya dengan lebih andal jika ukuran cache Anda bukan 1 adalah:

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.

Berhati-hatilah bahwa jika orang lain menggunakan urutan selama ini - mereka (atau Anda) mungkin mendapatkannya

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

Juga, Anda mungkin ingin mengatur cache NOCACHEsebelum reset dan kemudian kembali ke nilai aslinya setelah itu untuk memastikan Anda tidak menembolok banyak nilai.

Ollie
sumber
Hanya mencobanya tetapi saya tidak memiliki akses ke tabel 'all_afterences'. Apakah itu objek khusus yang hanya Anda lihat dengan kredensial admin?
frno
1
ALL_SEQUENCESadalah pandangan. Jika Anda tidak memiliki akses ke sana, cobalah memilih dari USER_SEQUENCESapakah urutannya ada di skema default Anda. (Anda tidak perlu sequence_owner = '<sequence_owner>'klausa untuk USER_SEQUENCES).
Ollie
15
The LAST_NUMBERdalam ALL_SEQUENCEStidak akan menjadi nomor terakhir yang sesi benar-benar diberi dan tidak akan menjadi nomor yang akan kembali dari panggilan ke sequence_name.nextvalpada umumnya. Dengan asumsi Anda telah menetapkan urutan ke CACHElebih dari 1 (default adalah 20), LAST_NUMBERakan menjadi nomor terakhir yang ada di cache. Tidak ada jaminan bahwa nomor ini akan benar-benar diberikan pada sesi apa pun.
Justin Cave
2
ALTER SEQUENCE seq INCREMENT BY -1;akan menjadi masalah kecuali seseorang dapat menjamin bahwa tidak ada sesi lain akan menelepon seq.nextval. Kalau tidak, urutannya akan membagikan nilai duplikat, yang biasanya bukan yang diinginkan.
Shannon Severance
1
OP memang mengatakan "Ini adalah cek setelah migrasi data" jadi itu bukan peregangan untuk menganggap DB tidak digunakan secara umum tetapi bisa menjadi masalah jika ini tidak terjadi.
Ollie
122

select MY_SEQ_NAME.currval from DUAL;

Perlu diingat bahwa ini hanya berfungsi jika Anda berlari select MY_SEQ_NAME.nextval from DUAL;di sesi saat ini.

RonK
sumber
1
Terima kasih banyak atas jawaban Anda. Saya harus menggunakan ini di dalam Boomi dan sedang mencari solusi naik turun
belajar ...
0

Jawaban asli saya secara faktual salah dan saya senang itu dihapus. Kode di bawah ini akan berfungsi dalam kondisi berikut a) Anda tahu bahwa tidak ada orang lain yang mengubah urutan b) urutan diubah oleh sesi Anda. Dalam kasus saya, saya mengalami masalah serupa di mana saya memanggil prosedur yang mengubah nilai dan saya yakin anggapan itu benar.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

Sayangnya, jika Anda tidak mengubah urutan dalam sesi Anda, saya percaya orang lain benar dalam menyatakan bahwa NEXTVAL adalah satu-satunya cara untuk pergi.

georgejo
sumber
0

Ini bukan jawaban, sungguh dan saya akan memasukkannya sebagai komentar seandainya pertanyaannya tidak dikunci. Ini menjawab pertanyaan:

Mengapa Anda menginginkannya?

Asumsikan Anda memiliki tabel dengan urutan sebagai kunci utama dan urutan dihasilkan oleh pemicu sisipan. Jika Anda ingin agar urutan tersedia untuk pembaruan berikutnya ke catatan, Anda harus memiliki cara untuk mengekstrak nilai itu.

Untuk memastikan Anda mendapatkan yang benar, Anda mungkin ingin membungkus permintaan INSERT dan RonK dalam transaksi.

Pertanyaan RonK:

select MY_SEQ_NAME.currval from DUAL;

Dalam skenario di atas, peringatan RonK tidak berlaku karena penyisipan dan pembaruan akan terjadi di sesi yang sama.

Ainsworth
sumber
0

Saya juga mencoba menggunakan CURRVAL, dalam kasus saya untuk mengetahui apakah beberapa proses memasukkan baris baru ke beberapa tabel dengan urutan itu sebagai Primary Key. Asumsi saya adalah bahwa CURRVAL akan menjadi metode tercepat. Tapi a) CurrVal tidak berfungsi, itu hanya akan mendapatkan nilai lama karena Anda berada di sesi Oracle lain, sampai Anda melakukan NEXTVAL di sesi Anda sendiri. Dan b) a select max(PK) from TheTablejuga sangat cepat, mungkin karena PK selalu diindeks. Atau select count(*) from TheTable. Saya masih bereksperimen, tetapi kedua SELECT sepertinya cepat.

Saya tidak keberatan ada celah secara berurutan, tetapi dalam kasus saya, saya berpikir untuk melakukan jajak pendapat, dan saya akan membenci gagasan kesenjangan yang sangat besar. Terutama jika SELECT sederhana akan sama cepatnya.

Kesimpulan:

  • CURRVAL sangat tidak berguna, karena tidak mendeteksi NEXTVAL dari sesi lain, CURRVAL hanya mengembalikan apa yang sudah Anda ketahui dari NEXTVAL sebelumnya
  • SELECT MAX (...) FROM ... adalah solusi yang baik, sederhana dan cepat, dengan asumsi urutan Anda terkait dengan tabel itu
Roland
sumber