Apakah ada cara untuk membuat Oracle
kueri berperilaku seperti mengandung MySQL limit
klausa?
Dalam MySQL
, saya bisa melakukan ini:
select *
from sometable
order by name
limit 20,10
untuk mendapatkan baris ke-21 hingga ke-30 (lewati 20 pertama, berikan 10 berikutnya). Baris dipilih setelah order by
, jadi itu benar-benar dimulai pada nama ke-20 secara abjad.
Dalam Oracle
, satu-satunya hal yang orang sebutkan adalah rownum
pseudo-kolom, tetapi dievaluasi sebelumnya order by
, yang artinya:
select *
from sometable
where rownum <= 10
order by name
akan mengembalikan satu set acak sepuluh baris yang dipesan dengan nama, yang biasanya tidak saya inginkan. Itu juga tidak memungkinkan untuk menentukan offset.
sql
oracle
pagination
sql-limit
Mathieu Longtin
sumber
sumber
ORDER BY
. Itulah inti dari pemesanan terlebih dahulu. Jika data yang mendasarinya berubah dan hasil Anda menyetel perubahan karenanya, mengapa tidak menunjukkan kepada pengguna hasil yang diperbarui alih-alih informasi yang ketinggalan zaman? Juga, manajemen negara adalah wabah yang harus dihindari sebanyak mungkin. Ini merupakan sumber komplikasi dan bug yang konstan; itu sebabnya fungsional menjadi sangat populer. Dan kapan Anda tahu akan berakhir seluruh hasil yang diatur dalam memori? Di web, Anda tidak memiliki cara untuk mengetahui kapan pengguna pergi.Jawaban:
Mulai dari Oracle 12c R1 (12,1), ada adalah sebuah baris membatasi klausa . Itu tidak menggunakan
LIMIT
sintaks akrab , tetapi dapat melakukan pekerjaan dengan lebih baik dengan lebih banyak opsi. Anda dapat menemukan sintaksis lengkap di sini . (Baca juga lebih lanjut tentang bagaimana ini bekerja secara internal di Oracle dalam jawaban ini ).Untuk menjawab pertanyaan awal, inilah pertanyaannya:
(Untuk versi Oracle sebelumnya, silakan merujuk ke jawaban lain dalam pertanyaan ini)
Contoh:
Contoh-contoh berikut dikutip dari halaman tertaut , dengan harapan mencegah pembusukan tautan.
Mendirikan
Apa yang ada di meja?
Dapatkan
N
baris pertamaDapatkan
N
baris pertama , jika barisN
th memiliki ikatan, dapatkan semua baris terikatx
% Atas barisMenggunakan offset, sangat berguna untuk pagination
Anda dapat menggabungkan offset dengan persentase
sumber
OFFSET FETCH
sintaks adalah gula sintaks. DetailAnda dapat menggunakan subquery untuk seperti ini
Lihat juga pada topik Pada ROWNUM dan batasi hasil di Oracle / AskTom untuk informasi lebih lanjut.
Pembaruan : Untuk membatasi hasil dengan batas bawah dan atas hal-hal menjadi sedikit lebih membengkak
(Disalin dari artikel AskTom yang ditentukan)
Pembaruan 2 : Dimulai dengan Oracle 12c (12.1) ada sintaks yang tersedia untuk membatasi baris atau mulai dari offset.
Lihat jawaban ini untuk lebih banyak contoh. Terima kasih kepada Krumia untuk petunjuknya.
sumber
Saya melakukan beberapa pengujian kinerja untuk pendekatan berikut:
Asktom
Analitik
Alternatif Singkat
Hasil
Tabel memiliki 10 juta catatan, mengurutkan pada baris datetime yang tidak diindeks:
Memilih 10 baris pertama yang dilakukan:
Memilih baris antara 100.000 dan 100.010:
Memilih baris antara 9,000,000 dan 9,000,010:
sumber
BETWEEN
hanyalah sebuah singkatan untuk>= AND <=
( stackoverflow.com/questions/4809083/between-clause-versus-and )offset
Sintaks baru memiliki rencana dan kinerja yang sama dengan pendekatan analitik.Solusi analitik dengan hanya satu kueri bersarang:
Rank()
dapat digantiRow_Number()
tetapi dapat mengembalikan lebih banyak catatan daripada yang Anda harapkan jika ada nilai duplikat untuk nama.sumber
rank()
itu juga perlu dicatatdense_rank()
yang mungkin lebih berguna untuk kontrol output karena yang terakhir tidak "melewati" angka, sedangkanrank()
bisa. Dalam kasus apa pun untuk pertanyaanrow_number()
ini paling cocok. Satu lagi tidak adalah teknik ini berlaku untuk db yang mendukung fungsi yang disebutkan.Pada Oracle 12c (lihat klausa pembatas baris dalam referensi SQL ):
sumber
LIMIT
dalam SQL: 2008 mereka kemudian harus mengambil daun dari buku Microsoft dan melanggar standar.LIMIT ... OFFSET
LIMIT n, m
(Lihat jawaban saya). Kemudian lagi, Oracle seharusnya diimplementasikanLIMIT n, m
sebagai gula sintaksis, karena setara denganOFFSET n ROWS FETCH NEXT m ROWS ONLY
.Pertanyaan pagination dengan pemesanan benar-benar rumit di Oracle.
Oracle menyediakan pseudocolumn ROWNUM yang mengembalikan nomor yang menunjukkan urutan di mana database memilih baris dari tabel atau sekumpulan tampilan gabungan.
ROWNUM adalah pseudocolumn yang membuat banyak orang terlibat masalah. Nilai ROWNUM tidak ditetapkan secara permanen ke baris (ini adalah kesalahpahaman umum). Mungkin membingungkan ketika nilai ROWNUM benar-benar ditetapkan. Nilai ROWNUM ditetapkan ke baris setelah melewati predikat filter permintaan tetapi sebelum agregasi permintaan atau penyortiran .
Terlebih lagi, nilai ROWNUM bertambah hanya setelah ditetapkan.
Inilah sebabnya mengapa permintaan followin tidak menghasilkan baris:
Baris pertama hasil kueri tidak lulus predikat ROWNUM> 1, jadi ROWNUM tidak naik ke 2. Karena alasan ini, tidak ada nilai ROWNUM yang lebih besar dari 1, akibatnya, kueri tidak mengembalikan baris.
Kueri yang didefinisikan dengan benar akan terlihat seperti ini:
Cari tahu lebih lanjut tentang pertanyaan pagination di artikel saya di blog Vertabelo :
sumber
SQL Standard
Seperti yang saya jelaskan dalam artikel ini , SQL: 2008 Standard menyediakan sintaks berikut untuk membatasi set hasil SQL:
Oracle 11g dan versi yang lebih lama
Sebelum versi 12c, untuk mengambil catatan Top-N, Anda harus menggunakan tabel turunan dan pseudocolumn ROWNUM:
sumber
Kurang pernyataan SELECT. Juga, kurang memakan kinerja. Kredit ke: [email protected]
sumber
Sebagai perpanjangan dari jawaban yang diterima Oracle secara internal menggunakan
ROW_NUMBER/RANK
fungsi.OFFSET FETCH
sintaksis adalah gula sintaksis.Itu bisa diamati dengan menggunakan
DBMS_UTILITY.EXPAND_SQL_TEXT
prosedur:Mempersiapkan sampel:
Pertanyaan:
teratur:
db <> demo biola
Mengambil teks SQL yang diperluas:
WITH TIES
diperluas sebagaiRANK
:dan offset:
sumber
Jika Anda tidak menggunakan Oracle 12C, Anda dapat menggunakan permintaan TOP N seperti di bawah ini.
Anda bahkan dapat memindahkan ini dari klausa dengan klausa sebagai berikut
Di sini sebenarnya kita membuat tampilan sebaris dan mengganti nama rownum sebagai rnum. Anda dapat menggunakan rnum dalam kueri utama sebagai kriteria filter.
sumber
ORDER BY
danrownum
secara terpisah. Pada dasarnya saya membuat sub-query yang memilikiORDER BY
klausa .rownum
harus di luar subquery.Saya mulai mempersiapkan ujian Oracle 1z0-047, divalidasi terhadap 12c Saat mempersiapkannya, saya menemukan peningkatan 12c yang dikenal sebagai 'FETCH FIRST'. Memungkinkan Anda untuk mengambil baris / batas baris sesuai kenyamanan Anda. Beberapa opsi tersedia dengannya
Contoh:
sumber
lebih besar dari nilai yang ditemukan
kurang dari nilai menemukan
sumber
ROW_NUMBER()
solusi berbasis telah diposting oleh Leigh Riffel. Dalam kecanduan ada kesalahan sintaksis dalam kode yang ditampilkan.Untuk setiap baris yang dikembalikan oleh kueri, pseudocolumn ROWNUM mengembalikan nomor yang menunjukkan urutan Oracle memilih baris dari tabel atau set baris yang digabungkan. Baris pertama yang dipilih memiliki ROWNUM 1, yang kedua memiliki 2, dan seterusnya.
Saya telah menerapkan ini di
oracle
server11.2.0.1.0
sumber
Dalam hal SQL-Developer, secara otomatis hanya mengambil 50 baris pertama. Dan jika kita gulir ke bawah, ia mengambil 50 baris lagi dan seterusnya!
Karenanya kita tidak perlu mendefinisikan, dalam hal alat sql-developer!
sumber
Di oracle
VAL
5 baris dipilih.
SQL>
sumber
(Belum diuji) sesuatu seperti ini dapat melakukan pekerjaan
Ada juga peringkat fungsi analitik, yang dapat Anda gunakan untuk memesan.
sumber
Sama seperti di atas dengan koreksi. Bekerja tetapi jelas tidak cantik.
Jujur, lebih baik menggunakan jawaban di atas.
sumber