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

   ROWNUM là gì?

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

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!

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ý
Đọc thêm  PGA trong Oracle là gì

Đó 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

Đọc thêm  Cấu hình kết nối trong PostgreSQL với pg_hba.conf

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

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é.

 

    KHÓA HỌC: QUẢN TRỊ ORACLE DATABASE THẬT LÀ ĐƠN GIẢN  Xem ngay!

 

   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

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *