You are on page 1of 26

1

 Con trỏ (cursor) là một đối tượng liên kết với một tập dữ liệu và cho phép
người lập trình làm việc với từng dòng của tập dữ liệu đó.
 Để xử lý một câu lệnh SQL, PL/SQL mở một vùng làm việc có tên là vùng
ngữ cảnh (context area). PL/SQL sử dụng vùng này để thi hành câu SQL và
chứa kết quả trả về. Vùng ngữ cảnh đó là phạm vi hoạt động của con trỏ.

cursor

context area
2
 Con trỏ đuợc khai báo tường minh (explicit cursor)
 Con trỏ không được khai báo tường minh hay còn gọi là con trỏ tiềm ẩn
(implicit cursor).

3
 Được tự động tạo bởi Oracle trong các lệnh DML: INSERT, UPDATE,
DELETE
 và câu lệnh Select … into … nếu kết quả trả về chỉ một dòng dữ liệu

4
 SQL%NOTFOUND: kết quả trả về là TRUE nếu câu lệnh SQL không tìm
thấy dữ liệu
 SQL%FOUND: kết quả trả về là TRUE nếu câu lệnh SQL tìm thấy dữ liệu
 SQL%ROWCOUNT: kết quả trả về là số dòng dữ liệu mà câu lệnh SQL tìm
thấy
 SQL%ISOPEN: kết quả trả về là TRUE nếu con trỏ đang ở trạng thái mở
 Trước khi thi hành câu SQL,các thuộc tính của con trỏ tiềm ẩn có giá trị
NULL

5
CREATE TABLE dept_temp AS SELECT * FROM departments;
DECLARE
dept_no NUMBER(4) := 270;
BEGIN
DELETE FROM dept_temp WHERE department_id = dept_no;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘Delete succeeded');
INSERT INTO dept_temp VALUES (270, 'Personnel', 200, 1700);
END IF;
END;
DROP TABLE employees_temp;
CREATE TABLE employees_temp AS
SELECT * FROM employees;

DECLARE
mgr_no NUMBER(6) := 122;
BEGIN
DELETE FROM employees_temp WHERE manager_id = mgr_no;
DBMS_OUTPUT.PUT_LINE
('Number of employees deleted: ' || TO_CHAR(SQL%ROWCOUNT));
END;
 Được tạo bởi người dùng cho câu truy vấn với kết quả nhiều hơn 1 dòng

8
 Cú pháp: CURSOR tên-cursor IS câu-lệnh-SELECT;
◦ Trong đó, câu lệnh SELECT phải chỉ ra các cột cụ thể cần lấy cho con trỏ này.
◦ Phần khai báo này phải được đặt trong vùng khai báo biến (trước BEGIN của khối
(Block)).
 Ví dụ:
CURSOR c_nv IS SELECT empno,sal FROM EMP;

9
 OPEN tên-cursor;
◦ Mở con trỏ thi hành câu truy vấn
 FETCH tên-cursor INTO biến1, biến2, …, biếnn;
hoặc
◦ FETCH tên-cursor INTO biến_có_kiểu_record;
◦ Lệnh FETCH dùng để gọi một dòng trong tập dữ liệu của con trỏ, có thể được lặp
để gọi tất cả các dòng của con trỏ.
 CLOSE tên-cursor
◦ Đóng con trỏ, giải phóng khỏi bộ nhớ

10
11
 Tập các mẫu tin được trả về từ câu lệnh SQL được gọi là active set
và được lưu tại context area

12
 Context area (đặt tên bởi cursor) như là chiếc hộp, và active set
là những món đồ bên trong hộp.
◦ Để lấy những món đồ, trước tiên phải mở (OPEN) hộp
◦ Sau đó đỗ (FETCH) từng món đồ ra.
◦ Sau khi hoàn tất, phải đóng (CLOSE)hộp lại.

13
14
15
16
1. Thuộc tính %NOTFOUND (đi kèm lệnh Fetch)
◦ Mang giá trị TRUE hoặc FALSE.
◦ %NOTFOUND bằng TRUE khi đã fetch đến dòng cuối cùng của con trỏ.
Ví dụ:

OPEN cur_first;
LOOP
FETCH cur_first INTO v_empno,v_sal;
EXIT WHEN cur_first%NOTFOUND;
END LOOP;

17
2.Thuộc tính %FOUND (đi kèm lệnh Fetch)
◦ Ngược với thuộc tính NOTFOUND.
◦ Ví dụ: OPEN cur_first;
LOOP
FETCH cur_first INTO v_empno,v_sal;
IF cur_first%FOUND THEN
………….
ELSE
CLOSE cur_first;
EXIT;
END IF;
END LOOP;

18
Explicit cursor – Thuộc tính
3.Thuộc tính %ROWCOUNT
Trả về số dòng của con trỏ đã được fetch.
Ví dụ:
LOOP
FETCH cur_first INTO v_empno,v_sal;
……….
IF cur_first%ROWCOUNT =1000 THEN
EXIT;
END IF;
…….
END LOOP;

19
Explicit cursor – Thuộc tính

4.Thuộc tính %ISOPEN


Trả về giá trị TRUE nếu con trỏ ở trạng thái mở.
Ví dụ:
IF cur_first%ISOPEN THEN
FETCH cur_first INTO v_empno,v_sal;
ELSE
OPEN cur_first;
END IF;

20
Ví dụ thuộc tính %ROWCOUNT
DECLARE
CURSOR c1 IS SELECT last_name FROM employees WHERE ROWNUM < 11;
name employees.last_name%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO name;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(c1%ROWCOUNT || '. ' || name);
IF c1%ROWCOUNT = 5 THEN
DBMS_OUTPUT.PUT_LINE('--- Fetched 5th record ---');
END IF;
END LOOP;
CLOSE c1;
END;
• Một con trỏ có thể nhận tham số là tham trị.
• Các tham số không được dùng để trả về giá trị cho cursor.

Ví dụ:
CURSOR cur_first (v_eno EMP.empno%TYPE) IS
SELECT empno, sal
FROM EMP
WHERE empno= v_eno;
Trong đó, v_eno là tham số của con trỏ. Khi thao tác với con trỏ có tham số
thì ta phải gọi tên con trỏ kèm theo giá trị của tham số.
Khi open cursor ta phải truyền vào giá trị của tham số:
open cur_first(22);
DECLARE
Passing emp_job employees.job_id%TYPE := 'ST_CLERK';
Parameters to emp_salary employees.salary%TYPE := 3000;
Explicit Cursors my_record employees%ROWTYPE;
CURSOR c1 (job VARCHAR2, max_wage NUMBER) IS
SELECT * FROM employees
WHERE job_id = job AND salary > max_wage;
BEGIN
-- Any of the following statements opens the cursor:
-- OPEN c1('ST_CLERK', 3000); OPEN c1('ST_CLERK', emp_salary);
-- OPEN c1(emp_job, 3000); OPEN c1(emp_job, emp_salary);
OPEN c1(emp_job, emp_salary);
LOOP
FETCH c1 INTO my_record;
EXIT WHEN c1%NOTFOUND;
-- process data record
DBMS_OUTPUT.PUT_LINE ('Name = ' || my_record.last_name || ', salary = ' ||
my_record.salary || ', Job Id = ' || my_record.job_id );
END LOOP;
END;
 https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/static.htm#LNPL
S00602
1. Xây dựng khối lệnh in danh sách nhân viên thuộc phòng “Marketing”
2. Xây dựng khối lệnh in danh sách mã phòng ban, tên phòng ban có ít hơn 3
nhân viên.
 Lưu ý: Sử dụng CSDL HR.sql
SET SERVEROUTPUT ON;
DECLARE
CURSOR c1 IS SELECT E.* FROM employees E JOIN DEPARTMENTS D
ON D.DEPARTMENT_ID=E.DEPARTMENT_ID AND D.DEPARTMENT_NAME='Marketing';
V_EMP employees%ROWTYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO V_EMP;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(C1%ROWCOUNT || ' ' ||V_EMP.FIRST_NAME || ' ' ||
V_EMP.LAST_NAME);
END LOOP;
CLOSE c1;
END;

You might also like