Có, nhiều người đang làm theo một thực hành xấu.
Kiểu xấu
Tôi đồng ý với @Osy rằng OPEN / FETCH / CLOSE thêm mã hoàn toàn không cần thiết. Tôi sẽ còn đi xa hơn nữa và nói rằng bạn hầu như không bao giờ nên sử dụng CURSOR
.
Trước hết, bạn thường muốn làm càng nhiều càng tốt trong SQL thuần túy. Nếu bạn cần sử dụng PL / SQL, hãy sử dụng con trỏ ngầm. Nó sẽ giúp bạn tiết kiệm một dòng mã và sẽ giúp bạn giữ các logic liên quan gần nhau hơn.
Tôi rất tin tưởng vào việc giữ cho các đơn vị mã riêng lẻ càng nhỏ càng tốt. Thoạt nhìn, nó có vẻ giống như một CURSOR
có thể giúp bạn làm điều này. Bạn có thể xác định SQL up top của mình ở một nơi, rồi thực hiện lặp PL / SQL sau.
Nhưng trên thực tế, lớp chuyển hướng bổ sung đó hầu như không bao giờ đáng giá. Đôi khi có rất nhiều logic trong SQL, và đôi khi rất nhiều logic trong PL / SQL. Nhưng trong thực tế, hiếm khi có ý nghĩa khi đặt nhiều logic phức tạp vào cả hai. Mã của bạn thường trông giống như sau:
for records in (<simple SQL>) loop
<complex PL/SQL>
end loop;
hoặc:
for records in
(
<complex SQL>
) loop
<simple PL/SQL>;
end loop;
Dù bằng cách nào, một trong các phần mã của bạn sẽ rất nhỏ. Độ phức tạp của việc tách hai đoạn mã đó lớn hơn độ phức tạp của một đoạn mã đơn lẻ, lớn hơn. (Nhưng đó rõ ràng là ý kiến của tôi.)
Hiệu suất kém
Có những tác động đáng kể về hiệu suất khi sử dụng OPEN / FETCH / CLOSE. Phương pháp đó chậm hơn nhiều hơn là sử dụng con trỏ for vòng lặp hoặc con trỏ ngầm.
Trình biên dịch có thể tự động sử dụng thu thập số lượng lớn trong một số vòng lặp for. Tuy nhiên, để trích dẫn từ bản trình bày Oracle " PL / SQL Performance — Debunking the Myths " , trang 122:
Đây là một ví dụ nhanh:
--Sample data
create table t(a number, b number);
insert into t select level, level from dual connect by level <= 100000;
commit;
--OPEN/FETCH/CLOSE
--1.5 seconds
declare
cursor test_cur is
select a, b from t;
test_rec test_cur%rowtype;
counter number;
begin
open test_cur;
loop
fetch test_cur into test_rec;
exit when test_cur%notfound;
counter := counter + 1;
end loop;
close test_cur;
end;
/
--Implicit cursor
--0.2 seconds
declare
counter number;
begin
for test_rec in (select a, b from t) loop
counter := counter + 1;
end loop;
end;
/