Cơ chế hoạt động của Rownum

   ORACLE ROWNUM là gì?

Giả sử bạn đang muốn lẩy ra 10 dòng đầu tiên của 1 bảng có 10 triệu dòng. Giải pháp thường sử dụng là dùng mệnh đề ROWNUM.

select * from customers where rownum < 11

 

ROWNUM là 1 cột ảo, nó tồn tại trong mỗi câu lệnh query trong Oracle. Giá trị của ROWNUM sẽ được gán cho các dòng 1,2,3…n của kết quả truy vấn (n là tổng số dòng).

Nó có 2 công dụng:

  • Lấy ra top n kết quả.
  • Dùng để phân trang (VD: kết quả được hiển thị theo từng trang trên website).

Nó rất hữu ích, tuy nhiên, đôi lúc có thể khiến DBA nhầm lẫn.

   Cách thức hoạt động của ROWNUM trong Oracle

   ROWNUM được sinh ra như thế nào?

Một trong những thắc mắc thường gặp nhất là: Thực sự khi nào rownum được gán?

Câu trả lời: Giá trị của ROWNUM được gán cho row, sau khi row đó qua bước lọc dữ liệu (mệnh đề where), nhưng trước khi thực hiện bước sắp xếp và tổng hợp (VD: mệnh đề order by và group by).

Vì nguyên nhân trên, khi bạn chạy câu lệnh bên dưới sẽ không có kết quả:

select *
from t
where ROWNUM > 1;

 

Bởi vì ROWNUM > 1 = false ở ngay row đầu tiên, nên ROWNUM không thể tiến tới 2. Do đó, sẽ không có giá trị ROWNUM nào lớn hơn 1!

 

   Thứ tự xử lý của câu lệnh có ROWNUM

Hãy xem tiếp một truy vấn có cấu trúc sau:

select ..., ROWNUM
from t
where <where clause>
group by <columns>
having <having clause>
order by <columns>;

Nó được xử lý theo thứ tự sau:

  • Mệnh đề FROM/WHERE được xử lý trước
  • ROWNUM được gán và tăng dần cho mỗi row là đầu ra từ mệnh đề FROM / WHERE.
  • Mệnh đề SELECT được xử lý
  • Mệnh đề GROUP BY được xử lý
  • Mệnh đề HAVING được xử lý
  • Mệnh đề ORDER BY được xử lý

Đó là lý do tại sao một truy vấn kiểu dưới đây gần như chắc chắn bị lỗi:

select *
from emp
where ROWNUM <= 5
order by sal desc;

 

Ý định của người viết câu truy vấn là lấy ra năm người được trả lương cao nhất.

Tuy nhiên, những gì câu truy vấn trả về sẽ là 5 row ngẫu nhiên đầu tiên được lấy ra, được sắp xếp theo mức lương (cột sal). Mã giả cho truy vấn này như sau:

ROWNUM = 1
for x in
( select * from emp )
loop
exit when NOT(ROWNUM <= 5)
OUTPUT record to temp
ROWNUM = ROWNUM+1
end loop
SORT TEMP

 

Nó lấy 5 row đầu tiên và sau đó sắp xếp chúng.

Một truy vấn với WHERE ROWNUM = 5 hoặc WHERE ROWNUM > 5 không có ý nghĩa. Điều này là do giá trị ROWNUM chỉ được gán cho một row khi nó đã vượt qua mệnh đề WHERE.

Đây là phiên bản chính xác của truy vấn này:

select *
from
( select *
from emp
order by sal desc )
where ROWNUM <= 5;

Câu truy vấn này sẽ sắp xếp bảng EMP theo cột SAL giảm dần và sau đó trả về 5 row đầu tiên mà nó gặp phải (5 nhân viên có mức lương cao nhất).

Tuy nhiên, Oracle Database không thực sự lấy ra và sắp xếp toàn bộ tập kết quả. Nó thông minh hơn thế, nhưng về mặt lý thuyết thì đó là những gì diễn ra.

Ở 1 bài khác, tôi sẽ giải thích điều này cho mọi người.

Tham khảo: https://blogs.oracle.com/connect/post/on-rownum-and-limiting-results

Hẹn gặp lại các bạn vào bài viết tiếp theo.

Bài tiếp theo:

Đọc thêm  Xử lý truy vấn Top N với ROWNUM

Nguồn: https://dangxuanduy.com/

 

Hiện tại, tôi có tổ chức đều đặn các khóa học về quản trị Oracle Database, tôi sẽ để thông tin ở đây, để bạn nào quan tâm về lịch học cũng như chương trình học có thể theo dõi nhé.

KHOÁ DÀNH CHO NGƯỜI MỚI

 KHÓA HỌC: QUẢN TRỊ ORACLE DATABASE THẬT LÀ ĐƠN GIẢN (ADMIN 1)  

CÁC KHOÁ NÂNG CAO:

 KHÓA HỌC ORACLE NÂNG CAO: QUẢN TRỊ KIẾN TRÚC MULTITENANT 12c 

 KHÓA HỌC ORACLE NÂNG CAO: QUẢN TRỊ HỆ THỐNG DATA GUARD  

CÁC KHOÁ COMBO:

 COMBO 1: ADMIN 1 + MULTITENANT 12c 

 COMBO 2: ADMIN 1 + DATA GUARD 

 COMBO 3: ADMIN 1 + MULTITENANT 12c + DATA GUARD 

LỊCH HỌC:

Mời bạn xem tại đây: LỊCH HỌC CÁC LỚP ORACLE 

ĐĂNG KÝ:

Form đăng ký

 

   Hãy tham gia group “Kho tài liệu kiến thức database” để cùng học hỏi và chia sẻ nhé.

Đặng Xuân Duy
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Phản hồi nội tuyến
Xem tất cả bình luận