Tại sao sử dụng con trỏ rõ ràng thay vì các vòng lặp thông thường?


12

Tôi đã viết các ứng dụng web cơ bản trong một năm (đối với Oracle db) và vì các chức năng khá đơn giản, hầu hết chúng ta đều sử dụng các vòng lặp FOR thông thường để lấy dữ liệu của mình:

for i in (select * from STUDENTS) loop
      htp.prn(i.student_last_name || ', ' || i.student_first_name || ' ' || i.student_dob);
end loop;

Nhưng, con trỏ dường như là cách 'đúng' để làm mọi việc. Tôi có thể tìm thấy nhiều thông tin về con trỏ là gì và các cách khác nhau để lặp qua chúng, nhưng tôi không thể tìm thấy lý do chắc chắn tại sao sử dụng chúng trên các vòng lặp FOR thông thường. Có phụ thuộc vào nhu cầu của thủ tục? Có những lợi thế vốn có tôi nên nhận thức?


Loại FORnày chỉ là một cách khác để sử dụng con trỏ. Xem các tài liệu: docs.oracle.com/cd/E11882_01/appdev.112/e10472/ Dù sao, htp.prn () làm gì?
dezso

Đó là một trong những chức năng đầu ra của chúng tôi. Vì vậy, bạn có một sở thích về phương pháp sử dụng?
ini

Đối với loại điều này, FORvòng lặp dễ đọc hơn nhiều, tôi nghĩ. Tôi có xu hướng sử dụng các con trỏ 'thực' chỉ khi tôi phải lùi lại, không chỉ về phía trước. Tôi hỏi câu hỏi khác bởi vì tôi có thể tưởng tượng một chức năng bảng thay vì htp.prn().
dezso

Điều đáng nói là cả hai dạng con trỏ đều có hiệu năng kém hơn một giải pháp SQL thuần túy - đặc biệt có liên quan đến các câu lệnh DML.
David Aldridge

Câu trả lời:


7

Một con trỏ có thể rõ ràng hoặc ẩn và một trong hai loại có thể được sử dụng trong vòng lặp FOR. Có hai khía cạnh thực sự cho câu hỏi của bạn.

  1. Tại sao sử dụng một vòng lặp FOR con trỏ rõ ràng trên một vòng lặp FOR con trỏ ẩn?

    • Sử dụng một vòng lặp FOR con trỏ rõ ràng khi truy vấn sẽ được sử dụng lại, nếu không thì một con trỏ ẩn được ưu tiên.
  2. Tại sao sử dụng vòng lặp với FETCH chứ không phải vòng lặp FOR không có FETCH rõ ràng?

    • Sử dụng FETCH bên trong một vòng lặp khi bạn cần thu thập hàng loạt hoặc khi bạn cần SQL động.

Dưới đây là một số thông tin hữu ích từ các tài liệu.

Ví dụ về con trỏ tiềm ẩn cho LOOP

BEGIN
   FOR vItems IN (
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name
   ) 
   LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/

Ví dụ về con trỏ rõ ràng cho LOOP

DECLARE
   CURSOR c1 IS
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name;
BEGIN
   FOR vItems IN c1 LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/

Con trỏ tiềm ẩn

Con trỏ ẩn là con trỏ phiên được xây dựng và quản lý bởi PL / SQL. PL / SQL mở một con trỏ ẩn mỗi khi bạn chạy câu lệnh CHỌN hoặc DML. Bạn không thể điều khiển một con trỏ ẩn, nhưng bạn có thể lấy thông tin từ các thuộc tính của nó.

Một con trỏ ẩn đóng lại sau khi câu lệnh liên quan của nó chạy; tuy nhiên, các giá trị thuộc tính của nó vẫn có sẵn cho đến khi một câu lệnh CHỌN hoặc DML khác chạy.

Các thuộc tính con trỏ ẩn là: SQL% ISOPEN, SQL% FOUND, SQL% NOTFOUND, SQL% ROWCOUNT, SQL% BULK_lawCOUNT, SQL% BULK_EXCEPTIONS

Con trỏ rõ ràng

Một con trỏ rõ ràng là một con trỏ phiên mà bạn xây dựng và quản lý. Bạn phải khai báo và xác định một con trỏ rõ ràng, đặt tên cho nó và liên kết nó với một truy vấn (thông thường, truy vấn trả về nhiều hàng). Sau đó, bạn có thể xử lý tập kết quả truy vấn theo một trong các cách sau:

Mở con trỏ tường minh (bằng câu lệnh OPEN), tìm nạp các hàng từ tập kết quả (với câu lệnh FETCH) và đóng con trỏ tường minh (bằng câu lệnh CLOSE).

Sử dụng con trỏ rõ ràng trong một con trỏ Câu lệnh FOR LOOP (xem "Bộ kết quả truy vấn Xử lý bằng con trỏ cho câu lệnh LOOP").

Bạn không thể gán giá trị cho một con trỏ rõ ràng, sử dụng nó trong một biểu thức hoặc sử dụng nó làm tham số chương trình con chính thức hoặc biến chủ. Bạn có thể thực hiện những việc đó bằng một biến con trỏ (xem "Biến con trỏ").

Không giống như một con trỏ ẩn, bạn có thể tham chiếu một con trỏ rõ ràng hoặc biến con trỏ theo tên của nó. Do đó, một con trỏ hoặc biến con trỏ rõ ràng được gọi là một con trỏ được đặt tên.

Con trỏ cho báo cáo LOOP

Câu lệnh FOR LOOP cho phép bạn chạy một câu lệnh CHỌN và sau đó lập tức lặp qua các hàng của tập kết quả. Tuyên bố này có thể sử dụng một con trỏ ngầm hoặc rõ ràng.


1
Các con trỏ ẩn tìm nạp 100 hàng cùng một lúc từ 10g trở đi.
David Aldridge

16

Mã bạn đã đăng đang sử dụng một con trỏ. Nó đang sử dụng một vòng lặp con trỏ ngầm.

Có những trường hợp sử dụng vòng lặp con trỏ rõ ràng (nghĩa là khai báo biến CURSOR trong phần khai báo) sẽ tạo ra mã sạch hơn hoặc hiệu suất tốt hơn

  1. Nếu bạn có các truy vấn phức tạp hơn mà bạn không thể cấu trúc lại thành các khung nhìn, nó có thể giúp mã dễ đọc hơn nếu vòng lặp của bạn lặp lại student_cursorthay vì bao gồm một câu lệnh SQL 30 dòng nhúng một loạt logic. Ví dụ: nếu bạn in ra tất cả các sinh viên bị xóa để tốt nghiệp và tham gia vào các bảng có hồ sơ học tập của họ, các yêu cầu của chương trình cấp bằng của họ, các bảng có thông tin về tổ chức học thuật, các bảng có thông tin về sách thư viện quá hạn, các bảng có thông tin về phí chưa thanh toán, ghi đè quản trị, v.v. có lẽ sẽ hợp lý khi cấu trúc lại mã để truy vấn này không bị kẹt ở giữa mã liên quan đến việc hiển thị danh sách cho người dùng. Điều đó có thể liên quan đến việc tạo ra một khung nhìn sẽ gói gọn tất cả logic này. Hoặc nó có thể liên quan đến việc tạo một con trỏ rõ ràng được khai báo là một phần của khối PL / SQL hiện tại hoặc trong một số khối PL / SQL cấp cao hơn (nghĩa là một con trỏ được khai báo trong một gói) để nó có thể được sử dụng lại. Hoặc nó có thể liên quan đến việc làm một cái gì đó khác để đóng gói và tái sử dụng (giả sử, tạo ra một chức năng bảng đường ống thay thế).
  2. Nếu bạn muốn sử dụng các hoạt động hàng loạt trong PL / SQL, bạn thường muốn sử dụng các con trỏ rõ ràng. Dưới đây là một chủ đề StackOverflow thảo luận về sự khác biệt hiệu suất giữa các con trỏ rõ ràng và ẩn . Nếu tất cả những gì bạn đang làm là gọi htp.prn, thì BULK COLLECTcó lẽ bạn sẽ không mua gì cho bạn. Trong các trường hợp khác, mặc dù, nó có thể dẫn đến cải thiện hiệu suất đáng kể.

2

Tôi thấy rằng nhiều nhà phát triển đang sử dụng các con trỏ rõ ràng thay vì các con trỏ ngầm từ thói quen cũ. Điều này bởi vì trở lại trong phiên bản Oracle 7, đây luôn là cách hiệu quả hơn. Ngày nay thường có cách khác. Đặc biệt với trình tối ưu hóa mà nếu cần có thể viết lại con trỏ ẩn cho các vòng lặp để thu thập hàng loạt.


0

Gần đây tôi đã phải viết lại một loạt các truy vấn từ một vòng lặp FOR ẩn thành các con trỏ rõ ràng. Lý do là các truy vấn đã lấy dữ liệu từ cơ sở dữ liệu bên ngoài thông qua liên kết và cơ sở dữ liệu này có mã hóa khác với cơ sở dữ liệu cục bộ của chúng tôi. Khi chuyển dữ liệu từ con trỏ ẩn sang một lỗi không liên tục loại bản ghi được xác định cục bộ xảy ra (chỉ trên một số hàng cụ thể nhất định). DBA của chúng tôi đã giải thích điều này cho chúng tôi, chúng tôi sẽ không thể tự mình đi đến tận cùng của điều này. Có vẻ như đây là một lỗi trong Oracle đã được báo cáo.

Chúng tôi được khuyên nên viết lại mọi thứ bằng cách sử dụng con trỏ rõ ràng và lỗi đã biến mất.

Không phải là lý do chính mà bạn có thể muốn sử dụng rõ ràng hơn ẩn, nhưng đáng lưu ý.

EDIT: Oracle 12c.


Bạn có thể thêm vào lỗi và / hoặc số ghi chú để những người đọc nó có thể biết thêm về các triệu chứng và nếu / khi điều này được giải quyết?
Leigh Riffel

Xin lỗi, báo cáo lỗi được thực hiện bởi một trong những DBA của chúng tôi, tôi không có quyền truy cập vào thông tin đó.
Robotron
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.