Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Sử dụng lệnh EXIT WHEN khi lặp qua CURSOR trong Oracle có phải là một cách thực hành không tốt không?

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;
/


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kiểm tra xem bảng có tồn tại trong cơ sở dữ liệu hay không - PL SQL

  2. Sự cố khi chuyển dự án .NET từ không được quản lý sang tổ hợp ODP.NET được quản lý

  3. Làm cách nào để lấy các ký tự được đánh số lẻ trong một chuỗi bằng SQL

  4. Oracle RESET_PACKAGE không đặt lại giá trị của một biến trong phiên

  5. Nhập blob thông qua SAS từ ORACLE DB