2008-10-27 41 views
71

Tôi không quen thuộc với Oracle như tôi muốn. Tôi có một số bản ghi 250k và tôi muốn hiển thị chúng 100 trang mỗi trang. Hiện tại tôi có một thủ tục lưu trữ truy lục tất cả một phần tư triệu bản ghi đến tập dữ liệu bằng bộ điều hợp dữ liệu và tập dữ liệu và phương thức dataadapter.Fill (tập dữ liệu) trên kết quả từ proc được lưu trữ. Nếu tôi có "Số trang" và "Số lượng bản ghi trên mỗi trang" dưới dạng giá trị số nguyên, tôi có thể chuyển thành tham số, thì cách nào tốt nhất để lấy lại chỉ phần cụ thể đó. Giả sử, nếu tôi vượt qua 10 dưới dạng số trang và 120 dưới dạng số trang, từ câu lệnh chọn, nó sẽ cho tôi từ 1880 đến 1200, hoặc một cái gì đó tương tự, toán học của tôi trong đầu tôi có thể bị tắt.Phân trang với Oracle

Tôi đang làm điều này trong .NET với C#, nghĩ rằng đó không phải là quan trọng, nếu tôi có thể làm cho nó ngay trên mặt sql, sau đó tôi nên được mát mẻ.

Cập nhật: Tôi đã có thể sử dụng đề xuất của Brian và nó đang hoạt động rất tốt. Tôi muốn làm việc trên một số tối ưu hóa, nhưng các trang đang đến trong 4 đến 5 giây thay vì một phút, và kiểm soát phân trang của tôi đã có thể tích hợp rất tốt với procs lưu trữ mới của tôi.

Trả lời

112

Something như thế này nên làm việc: From Frans Bouma's Blog

SELECT * FROM 
(
    SELECT a.*, rownum r__ 
    FROM 
    (
     SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%' 
     ORDER BY OrderDate DESC, ShippingDate DESC 
    ) a 
    WHERE rownum < ((pageNumber * pageSize) + 1) 
) 
WHERE r__ >= (((pageNumber-1) * pageSize) + 1) 
+0

là rownum một từ thuộc? –

+3

Có một cột 'được xây dựng trong' mà Oracle hỗ trợ, nó luôn bắt đầu ở mức 1 và gia số cho mỗi hàng. Vì vậy, trong đoạn mã này, nếu bạn có 1000 hàng, thứ tự sắp xếp được áp dụng và sau đó mỗi hàng được gán một bảng phân phối. Các lựa chọn bên ngoài (s) sử dụng những số hàng để xác định vị trí 'trang' bạn đang tìm kiếm dựa trên các trang của bạn. –

+5

Điều này là tốt đẹp, nhưng khủng khiếp chậm trên lựa chọn lớn, chỉ cần kiểm tra những gì sẽ là thời gian để chọn 0 đến 1000 và 500.000 đến 501.000 ... Tôi đã sử dụng loại cấu trúc chọn bây giờ tôi đang tìm kiếm một workaround. – newhouse

109

Ask Tom trên pagination và chức năng phân tích rất, rất hữu ích.

Đây là đoạn trích từ trang đó:

select * from (
    select /*+ first_rows(25) */ 
    object_id,object_name, 
    row_number() over 
    (order by object_id) rn 
     from all_objects) 
    where rn between :n and :m 
     order by rn; 
+3

Đây thực sự là một triển khai tốt hơn nhiều, mặc dù rất khó để tìm thấy trên bài đăng đó. Khi bạn có nhiều trang lớn, câu trả lời khác cũng phải đi qua tất cả các hàng từ các trang trước đó. Trong các truy vấn phức tạp, điều này có nghĩa là các trang sau thực hiện tồi tệ hơn các trang trước đó. – tallseth

+0

@tallseth Bạn nói đúng. Thật khó để tìm thấy nó trên trang đó. Trích được thêm vào. – Chobicus

4

Hãy thử như sau:

SELECT * 
FROM 
    (SELECT FIELDA, 
    FIELDB, 
    FIELDC, 
    ROW_NUMBER() OVER (ORDER BY FIELDC) R 
    FROM TABLE_NAME 
    WHERE FIELDA = 10 
) 
WHERE R >= 10 
AND R <= 15; 

qua [tecnicume]

31

Vì lợi ích của sự hoàn chỉnh, cho những người tìm kiếm một giải pháp hiện đại hơn, trong Oracle 12c có một số tính năng mới bao gồm phân trang tốt hơn và xử lý hàng đầu.

Paging

Các phân trang trông như thế này:

SELECT * 
FROM user 
ORDER BY first_name 
OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY; 

Lên trên N ghi

Bắt các hồ sơ đầu trông như thế này:

SELECT * 
FROM user 
ORDER BY first_name 
FETCH FIRST 5 ROWS ONLY 

Lưu ý rằng cả hai ví dụ truy vấn trên đều có các điều khoản ORDER BY. Các lệnh mới tôn trọng các lệnh này và được chạy trên dữ liệu được sắp xếp.

Tôi không thể tìm thấy trang tham chiếu tốt của Oracle cho FETCH hoặc OFFSET nhưng this page có tổng quan tuyệt vời về các tính năng mới này.

5

Chỉ muốn tóm tắt câu trả lời và nhận xét. Có một số cách thực hiện phân trang.

Trước khi oracle 12c không có chức năng OFFSET/FETCH, vì vậy, hãy xem whitepaper như @jasonk đề xuất. Đó là bài viết hoàn chỉnh nhất tôi tìm thấy về các phương pháp khác nhau với giải thích chi tiết về những ưu điểm và nhược điểm.Phải mất một lượng thời gian đáng kể để sao chép và dán chúng ở đây, vì vậy tôi sẽ không làm điều đó.

Ngoài ra còn có một bài viết hay từ những người tạo jooq giải thích một số thông báo chung với oracle và các cơ sở dữ liệu khác. jooq's blogpost

Tin vui, vì oracle 12c chúng tôi có chức năng OFFSET/FETCH mới. OracleMagazine 12c new features. Vui lòng tham khảo "Top-N Queries và Pagination"

Bạn có thể kiểm tra phiên bản oracle của bạn bằng cách phát hành các tuyên bố sau

SELECT * FROM V$VERSION