Con trỏ trong cơ sở dữ liệu

Bách khoa toàn thư mở Wikipedia
Buớc tưới chuyển hướng Bước tới tìm kiếm

Trong khoa học máy tính, con trỏ trong cơ sở dữ liệu là một cấu trúc điều khiển cho phép traversal (duyệt) qua các bản ghi trong cơ sở dữ liệu. Các cursor tạo điều kiện xử lý tiếp theo kết hợp với việc traversal, chẳng hạn như thu hồi, bổ sung và loại bỏ các bản ghi cơ sở dữ liệu. Các cursor đặc trưng của phép duyệt làm cho con trỏ tương tự như khái niệm ngôn ngữ lập trình của hướng đối tượng. Các con trỏ được sử dụng bởi các lập trình viên cơ sở dữ liệu để xử lý từng hàng và trả về bởi các truy vấn hệ thống cơ sở dữ liệu. Con trỏ cho phép thao tác các tập kết quả cùng một lúc. Trong trường hợp này, một con trỏ cho phép các hàng trong một bộ kết quả được xử lý tuần tự. Trong các thủ tục SQL, một cursor sẽ làm cho nó có thể định nghĩa một tập kết quả (một tập hợp các dòng dữ liệu) và thực hiện logic phức tạp trên cơ sở hàng bằng hàng. Bằng cách sử dụng cùng một thủ tục SQL cũng có thể định nghĩa một tập kết quả và trả lại trực tiếp cho người gọi thủ tục SQL hoặc ứng dụng khách. Con trỏ chỉ có thể tham chiếu một hàng tại một thời điểm, nhưng có thể di chuyển đến các hàng khác của bộ kết quả khi cần.

Vấn đề đặc ra là:
Các câu lệnh trong SQL đều thao tác lên nhiều dòng dữ liệu thỏa điều kiện WHERE cùng lúc mà không thể thao tác trên từng dòng cụ thể. Vì thế, cursor được xem như một cách giải quyết vấn đề đơn giản nhất. Cursor là kiểu dữ liệu có thể duyệt qua từng dòng kết quả trả về của câu lệnh SELECT giúp chúng ta có thể xử lý khác nhau cho từng kết quả mà ta mong muốn. Nhưng lại tồn tại khuyết điểm là xử lý rất chậm

Cách sử dụng con trỏ[sửa | sửa mã nguồn]

Để sử dụng con trỏ trong cơ sở dữ liệu, chúng ta cần:

  1. Khai báo một con trỏ xác định một tập kết quả
  2. Thiết lập kết quả cho con trỏ
  3. Gán dữ liệu cho các biến cục bộ cần thiết cho con trỏ và một hàng.
  4. Đóng cursor khi hoàn thành

Để làm viêc với con trỏ chúng ta cần sử dụng câu lệnh SQL. Để con trỏ biết được cơ sở dữ liệu ta dùng DECLARE...CURSOR để chỉ định con trỏ:

Ví dụ[sửa | sửa mã nguồn]

1 -- KHAI BÁO CON TRỎ
2 
3 DECLARE ten_con_tro [SCROLL] CURSOR
4 		FOR
5 			SELECT 
6 			FROM 
7 			WHERE
8 		[FOR {READ ONLY | UPDATE [OF ten_cot [truong]]}]
Trong đó:
  • SCROLL: cho phép con trỏ di chuyển lên xuống, qua lại giữa các mẫu tin.
  • READ ONLY: không cho phép thực thi các hành động như update,...
  • UPDATE: xác định khả năng cập nhật của con trỏ, nếu OF được chỉ định thì chỉ có những cột, những trường trong danh sách được chỉnh sửa. Ngoài ra, chúng ta cũng có thể khởi tạo riêng con trỏ rồi mới gán lệnh SELECT cho con trỏ, như sau:
0 -- KHAI BAO CON TRỎ RIÊNG
1 
2 DECLARE @ten_con_tro CURSOR
3 
4 SET @ten_con_tro = CURSOR FOR SELECT...

Trước khi con trỏ có thể sử dụng được, chúng ta còn mở cursor ra, khi lệnh mở thành công, cursor sẽ được thực thi đầu tiên trong tập kết quả:

0 -- MỞ CON TRỎ
1 
2 OPEN [GLOBAL] ten_con_tro | @ten_con_tro
GLOBAL: gọi biến toàn cục (mặc định sẽ là cục bộ (local)).

Sau khi đã mở Cursor thành công, chúng ta có thể truy cập được đến con trỏ bằng lệnh FETCH:

0 -- TRUY CẬP CON TRỎ
1 
2 FETCH [NEXT | PRIOR | FIRST | LAST | ABSOLUTE {n | @nVar} | RELATIVE {n | @nVar}]
3 
4 FROM [GLOBAL] ten_con_tro | @ten_con_tro
5 
6 [INTO @ten_bien[du_lieu]]
Trong đó:
  • NEXT, PRIOR, FIRST, LAST: chỉ định cách đọc dữ liệu.
  • ABSOLUTE: chỉ định n số dòng dữ liệu cần đọc. Nếu:
  • n = 0: không có giá trị trả về.
  • n < 0: xuất phát từ phần đáy dữ liệu.
  • n > 0: xuất phát từ phần đỉnh dữ liệu.
  • RELATIVE cũng giống như ABSOLUTE nhưng bắt đầu từ vị trí hiện tại.

Ngoài ra, chúng ta còn có lệnh @@FETCH_STATUS để check xem hệ thống đọc dữ liệu thành công hay thất bại

Bước cuối cùng là đóng Cursor bằng lệnh hai câu lệnh CLOSE hoặc DEALLOCATE

0 -- ĐÓNG CURSOR
1 
2 CLOSE [GLOBAL] ten_con_tro | @ten_con_tro
HOẶC
0 -- GIẢI PHÓNG BỘ NHỚ
1 
2 DEALLOCATE [GLOBAL] ten_con_tro | @ten_con_tro

Lưu ý: CLOSEDEALLOCATE sẽ có sự khác biệt. Với CLOSE chúng ta sẽ đóng cursor lại nhưng có thể tái sử dụng lại ở lần sau. Còn DEALLOCATE sẽ giải phóng hoàn toàn cursor ra khỏi bộ nhớ, vì vậy nếu có lệnh nào tham chiếu tới cursor có thể gây ra lỗi.

"WITH HOLD"[sửa | sửa mã nguồn]

Các con trỏ thường được đóng tự động khi kết thúc giao dịch, nghĩa là khi COMMIT hoặc ROLLBACK (hoặc chấm dứt giao dịch) xảy ra. Hành vi đó có thể được thay đổi nếu con trỏ được khai báo sử dụng mệnh đề WITH HOLD (mặc định là không HOLD). Một con trỏ giữ được giữ qua COMMIT và đóng lại khi ROLLBACK. (Một số DBMS đi chệch hướng tiêu chuẩn này và cũng giữ các con trỏ có thể lưu giữ được mở trên ROLLBACK).

0 -- WITHHOLD
1 
2 DECLARE ten_con_tro CURSOR  WITH HOLD  FOR SELECT.... FROM....

Câu lệnh định dạng cập nhật hoặc xóa[sửa | sửa mã nguồn]

Các con trỏ không chỉ được sử dụng để lấy dữ liệu từ DBMS vào một ứng dụng mà còn để xác định một hàng trong một bảng sẽ được cập nhật hoặc xóa. Tiêu chuẩn SQL: 2003 xác định các câu lệnh SQL định vị bản cập nhật và xóa cho mục đích đó. Các tuyên bố như vậy không sử dụng mệnh đề WHERE thông thường với các vị từ. Thay vào đó, một con trỏ xác định hàng. Con trỏ phải được mở và đã được định vị trên một hàng bằng câu lệnh FETCH.

0 --Định vị UPDATE
1 
2 UPDATE ten_bang
3 SET    ...
4 WHERE  CURRENT OF ten_con_tro
0 --Định vị DELETE
1 
2  DELETE
3  FROM   ten_bang
4  WHERE  CURRENT OF ten_con_tro

Con trỏ phải hoạt động trên một bộ kết quả có thể cập nhật để thực hiện thành công bản cập nhật hoặc xóa. Nếu không, DBMS sẽ không biết làm thế nào để áp dụng các thay đổi dữ liệu vào các bản khi sử dụng đến trong con trỏ.

Nhược điểm của con trỏ[sửa | sửa mã nguồn]

Tìm nạp một hàng từ con trỏ có thể dẫn đến lặp một chuyến đi server-client mạng mỗi lần. Điều này sử dụng băng thông mạng nhiều hơn bình thường cần cho việc thực hiện một câu lệnh SQL đơn lẻ như DELETE, ... . Các chuyến đi lặp đi lặp lại có thể làm giảm đáng kể tốc độ của hoạt động bằng con trỏ. Một số DBMS cố gắng giảm hiệu ứng này bằng cách sử dụng tìm nạp khối. Nạp khối có nghĩa là nhiều hàng được gửi cùng nhau từ máy chủ đến máy khách. Các khách hàng lưu trữ một khối toàn bộ hàng trong một bộ nhớ đệm và lấy ra các hàng từ đó cho đến khi bộ đệm đó bị trống. Các con trỏ phân bổ các tài nguyên trên máy chủ, chẳng hạn như khóa, gói, quy trình, và lưu trữ tạm thời. Ví dụ, Microsoft SQL Server thực hiện các con trỏ bằng cách tạo một bảng tạm thời và nạp cho nó bộ kết quả truy vấn. Nếu con trỏ không được đóng đúng cách (deallocated), các tài nguyên sẽ không được giải phóng cho đến khi phiên bản SQL (kết nối) được đóng lại. Sự lãng phí tài nguyên này trên máy chủ có thể dẫn đến sự xuống cấp.

Ví dụ[sửa | sửa mã nguồn]

DÙNG CON TRỎ ĐỂ TRUYỀN DỮ LIỆU TỪ BẢNG NÀY SANG BẢNG KIA:

 0 DECLARE @ID INT, @NAME NVARCHAR(15); --KHAI BÁO TRƯỜNG @ID VÀ @NAME
 1 DECLARE CONTRO CURSOR FOR --KHAI BÁO CON TRỎ CHO CÂU LỆNH SELECT
 2 	SELECT EMP_ID, NAME
 3 	FROM EMPLOYEES
 4 	ORDER BY EMP_ID
 5 ----------------------------------------
 6 OPEN CONTRO --MỞ CON TRỎ
 7 ----------------------------------------
 8 FETCH NEXT FROM CONTRO --SỬ DỤNG CON TRỎ
 9 	INTO @ID, @NAME --ĐƯA GIÁ TRỊ VÀO HAI TRƯỜNG
10 	WHILE @@FETCH_STATUS = 0 --ĐIỀU KIỆN ĐỂ THỰC THỊ CON TRỎ
11 ----------------------------------------
12 /* BẮT ĐẦU TRUYỀN THAM SỐ VÀO BẢNG EMPLOYEES_NAME BẰNG CÂU LỆNH INSERT INTO
13 	BẰNG CÁCH SỬ DỤNG CON TRỎ */
14 BEGIN
15 	INSERT INTO EMPLOYEES_NAME 
16 		(ID, NAME)
17 	VALUES (@ID, @NAME)
18 	FETCH NEXT FROM CONTRO
19 	INTO @ID, @NAME
20 END
21 CLOSE CONTRO --ĐÓNG CON TRỎ
22 -- DEALLOCATE CONTRO

—CTUET_DBMS_Group3

Tham khảo[sửa | sửa mã nguồn]