Bạn đã không nói liệu bạn có dự định điều chỉnh "X" và "Y" mỗi khi bạn thực hiện phân trang hay không. Nếu bạn không làm như vậy thì cách tiếp cận có lẽ chỉ hợp lệ nếu bạn có độ tin cậy cao rằng dữ liệu khá tĩnh.
Hãy xem xét ví dụ sau:
Bảng T của tôi có dấu thời gian ngày 100 hàng cho "hôm nay", với ID =1 đến 100 tương ứng và tôi muốn 20 hàng cuối cùng cho trang đầu tiên của mình. Vì vậy, tôi làm điều này:
select *
from T
where date_col = trunc(sysdate)
order by id desc
fetch first 20 rows only
Tôi chạy truy vấn của mình và nhận được ID =100 giảm xuống còn 80. Cho đến nay rất tốt - tất cả đều nằm trên trang của người dùng và họ mất 30 giây để đọc dữ liệu. Trong thời gian đó, 17 bản ghi khác đã được thêm vào bảng (ID =101 đến 117).
Bây giờ người dùng nhấn "Trang tiếp theo"
Bây giờ tôi chạy lại truy vấn để lấy bộ tiếp theo
select *
from T
where date_col = trunc(sysdate)
order by id desc
offset 20 fetch next 20 rows only
Họ sẽ không nhìn thấy các hàng từ 80 đến 60, đó là mong đợi của họ, vì dữ liệu đã thay đổi. Họ sẽ
a) lấy các hàng ID =117 xuống 97 và bỏ qua chúng do OFFSETb) sau đó lấy các hàng ID =97 xuống 77 để được hiển thị trên màn hình
Họ sẽ bối rối bởi vì họ đang nhìn thấy khá nhiều tập hợp các hàng giống như họ đã làm trên trang đầu tiên.
Để phân trang chống lại việc thay đổi dữ liệu, bạn thường muốn tránh xa điều khoản bù đắp và sử dụng ứng dụng của mình để ghi lại vị trí của bạn, tức là
Trang 1
select *
from T
where date_col = trunc(sysdate)
order by id desc
fetch first 20 rows only
Tôi tìm nạp ID =100 xuống 80 ... Tôi ghi chú lại trong số 80. Truy vấn tiếp theo của tôi sau đó sẽ là
select *
from T
where date_col = trunc(sysdate)
AND ID<80
order by id desc
fetch first 20 rows only
và truy vấn tiếp theo của tôi sẽ là
select *
from T
where date_col = trunc(sysdate)
AND ID<60
order by id desc
fetch first 20 rows only
và vân vân.