Nó cải thiện hiệu suất đáng kể (trung bình hàng chục phần trăm) trên các truy vấn mà không thể giải quyết bằng cách tra cứu chỉ mục đơn giản, ví dụ:bảng tham gia, tuy nhiên nó có khả năng ẩn dữ liệu / lỗi ứng dụng.
Cho phép có một bảng:
create table t (id number(10,0), padding varchar2(1000));
- cố ý không sử dụng PK để làm cho ví dụ đơn giản nhất có thể. Phần đệm được sử dụng để mô phỏng tải dữ liệu thực trong mỗi bản ghi
với nhiều bản ghi:
insert into t (id, padding)
select rownum, rpad(' ', 1000) from dual connect by level < 10000
Bây giờ nếu bạn hỏi điều gì đó như
select 1 into ll_exists
from t where id = 5;
DB phải xem qua toàn bộ bảng cho dù nó tìm thấy bản ghi phù hợp duy nhất trong khối dữ liệu đầu tiên (theo cách này chúng ta không thể biết vì nó có thể được chèn bằng nhiều cách khác nhau) hay ở cuối cùng. Đó là bởi vì nó không biết rằng chỉ có một bản ghi phù hợp. Mặt khác, nếu bạn sử dụng ... và rownum =1 thì nó có thể ngừng duyệt qua dữ liệu sau khi bản ghi được tìm thấy vì bạn đã nói với nó rằng không có (hoặc không cần) bản ghi phù hợp khác.
Hạn chế là với ràng buộc rownum, bạn có thể nhận được kết quả không xác định nếu dữ liệu chứa nhiều hơn một bản ghi có thể xảy ra.
select id into ll_id
from t where mod (id, 2) = 1
and rownum = 1;
thì tôi có thể nhận được từ DB câu trả lời 1 cũng như 3 cũng như 123 ... thứ tự không được đảm bảo và đây là hậu quả. (nếu không có điều khoản rownum, tôi sẽ nhận được một ngoại lệ TOO_MANY_ROWS. Nó tùy thuộc vào tình huống mà cái nào tồi tệ hơn)
Nếu bạn thực sự muốn truy vấn mà kiểm tra tồn tại thì hãy VIẾT nó theo cách đó.
begin
select 'It does'
into ls_exists
from dual where
exists (your_original_query_without_rownum);
do_something_when_it_does_exist
exception
when no_data_found then
do_something_when_it_doesn't_exist
end;