Khi làm việc với dữ liệu trong SQL Server, ngoài các câu lệnh cơ bản như SELECT, INSERT, UPDATE, DELETE để thao tác dữ liệu chúng ta sẽ còn rất nhiều chức năng khác hiếm nghe nghe đến và sử dụng. Một trong số đó là lặp đi lặp lại từng dòng dữ liệu hoặc một tập dữ liệu cụ thể. Trong SQL, cung cấp "cursor" để giúp chúng ta xử lý và làm việc trong trường hợp này.
1. Cursor trong SQL Server là gì?
Cursor trong SQL Server được hiểu đơn giản là một công cụ cho phép chúng ta duyệt qua từng dòng của dữ liệu trong một tập dữ liệu. Thông thường khi ta sử dụng câu SELECT để truy vấn dữ liệu, kết quả trả về thường sẽ có rất nhiều dòng. Trong trường hợp chúng ta cần truy cập từng dòng dữ liệu, cursor là một chức năng hỗ trợ ta làm việc này. Với cursor chúng ta có thể thực hiện các thao tác xử lý tùy chỉnh trên từng dòng dữ liệu trong tập kết quả theo thứ tự.
2. Cách sử dụng Cursor trong SQL Server
Trong SQL Server chúng ta có những bước cơ bản sau để thao tác với cursor:
- Khai báo Cursor: Đầu tiên chúng ta cần khai báo và liên kết một biến cursor với một câu SELECT để lấy dữ liệu cho quá trình xử lý và sử dụng cursor về sau.
- Mở Cursor: Sau khi đã khai báo cursor và tập dữ liệu được sử dụng cho cursor chúng ta sẽ mở cursor để bắt đầu tập dữ liệu như đã khai báo ở trên. Lúc này, tập dữ liệu sẽ được đưa vào cursor để xử lý.
DECLARE @StudentID INT
DECLARE @TotalScore INT
- Khai báo cursor
DECLARE StudentCursor CURSOR FOR SELECT StudentID, SUM(Score) AS TotalScore FROM DiemHocSinh GROUP BY StudentID
- Mở cursor
OPEN StudentCursor
- Duyệt dòng dữ liệu: Với lệnh FETCH chúng ta có thể duyệt qua từng dòng dữ liệu trong cursor. Các lệnh FETCH cho phép chúng ta lấy dữ liệu từ dòng hiện tại của cursor.
- Xử lý dữ liệu: Sau khi đã có dữ liệu từ cursor thì chúng ta sẽ thao tác xử lý, biến đổi trên dòng dữ liệu hiện tại.
- Lặp lại: Các bước xử lý dữ liệu sẽ được lặp lại trên từng dòng cursor cho đến khi hoàn tất.
- Lấy dòng dữ liệu đầu tiên
FETCH NEXT FROM StudentCursor INTO @StudentID, @TotalScore
- Duyệt qua từng dòng dữ liệu
WHILE @@FETCH_STATUS = 0
BEGIN
- Thực hiện thao tác xử lý - ví dụ: lưu tổng điểm vào bảng KetQuaHocTap
INSERT INTO KetQuaHocTap(StudentID, TotalScore) VALUES (@StudentID, @TotalScore)
- Lấy dòng dữ liệu tiếp theo
FETCH NEXT FROM StudentCursor INTO @StudentID, @TotalScore
END
- Đóng cursor: Đây là một phần rất quan trọng trong khi làm việc với cursor đó là đóng cursor. Bước này luôn cần được thực hiện để giải phóng lượng tài nguyên mà cursor đã chiếm dụng trong quá trình xử lý.
- Đóng cursor và giải phóng tài nguyên
CLOSE StudentCursor
DEALLOCATE StudentCursor
- Tóm tắt hoàn chỉnh các bước sử dụng cursor:
DECLARE @StudentID INT
DECLARE @TotalScore INT
- Khai báo cursor
DECLARE StudentCursor CURSOR FOR SELECT StudentID, SUM(Score) AS TotalScore FROM DiemHocSinh GROUP BY StudentID
- Mở cursor
OPEN StudentCursor
- Lấy dòng dữ liệu đầu tiên
FETCH NEXT FROM StudentCursor INTO @StudentID, @TotalScore
- Duyệt qua từng dòng dữ liệu
WHILE @@FETCH_STATUS = 0
BEGIN
- Thực hiện thao tác xử lý - ví dụ: lưu tổng điểm vào bảng KetQuaHocTap
INSERT INTO KetQuaHocTap(StudentID, TotalScore) VALUES (@StudentID, @TotalScore)
- Lấy dòng dữ liệu tiếp theo
FETCH NEXT FROM StudentCursor INTO @StudentID, @TotalScore
END
- Đóng cursor và giải phóng tài nguyên
CLOSE StudentCursor
DEALLOCATE StudentCursor
3. Hiệu năng của Cursor trong SQL Server
- Tần suất truy cập cơ sở dữ liệu: Với mỗi lần truy vấn dữ liệu từ cursor với lệnh FETCH lúc này một truy vấn SQL được thực hiện. Vì thế, điều này sẽ có thể dẫn đến tần suất truy cập cơ sở dữ liệu cao bất thường, khiến cho hiệu suất thực hiện các tác vụ khác của cơ sở dữ liệu giảm đi, đặc biệt cần chú ý khi tập dữ liệu quá lớn.
- Mở và đóng cursor: Trong khi ta mở và đóng cursor nó sẽ tạo ra một lượng tài nguyên tạm thời, việc này gây tốn thời gian và tài nguyên của cơ sở dữ liệu. Khi mở và đóng cursor nhiều có thể giảm hiệu năng của cơ sở dữ liệu.
4. Hạn chế của Cursor trong SQL Server
- Tài nguyên: Bản chất cursor sẽ phải tạo ra một bản sao tạm thời của tập dữ liệu mà nó xử lý, việc này gây ra tốn tài nguyên. Cho nên việc sử dụng cursor có thể sẽ gây lên những ảnh hưởng không tốt để hiệu năng cơ sở dữ liệu
- Khó đọc và bảo trì: Khi sử dụng cursor, mã SQL thường trở nên phức tạp và khó đọc hơn. Điều này khiến mã khó bảo trì và gỡ lỗi hơn.
- Khả năng xung đột và khóa: Trong các cơ sơ dữ liệu có tần suất truy xuất dữ liệu lớn, việc sử dụng cursor có thể gây ra xung đột và khiến cho các dữ liệu đang xử lý trong cursor bị khóa lại. Việc này khiến cho các hoạt động khác trên cũng bảng hay tập dữ liệu không thể xử lý đồng thời.
- Hiệu suất kém: Vì cursor sẽ truy cập cơ sở dữ liệu ở mỗi lệnh FETCH cho nên việc sử dụng cursor có thể gây ra tình trạng hiệu suất kém do tần suất truy cập cơ sở dữ liệu quá lớn gây tốn tài nguyên.
5. Lời khuyên
- Sử dụng tập hợp: Ngoài cursor, chúng ta có thể xem xét việc sử dụng các phương pháp xử lý khác như JOIN, subquery và các câu lệnh UPDATE/INSERT tập hợp để thực hiện công việc như sử dụng cursor.
- Tối ưu hóa: Nếu trong trường hợp chúng ta bắt buộc phải sử dụng cursor, thì hãy chú ý đến việc tối ưu hóa mã SQL để giảm tối đa tần suất truy cập cơ sở dữ liệu sẽ giúp tối ưu hóa hiệu suất.
- Sử dụng chỉ khi cần thiết: Sử dụng cursor khi thực sự cần thiết, đối với những truy vấn SQL không thể sử dụng các câu lệnh tập hợp.
Tổng kết
Cursor trong SQL Server là một công cụ mạnh mẽ cho phép bạn thực hiện các thao tác tùy chỉnh trên từng dòng dữ liệu trong tập kết quả. Tuy nhiên, việc sử dụng cursor cần được xem xét cẩn thận vì tác động đến hiệu năng và tài nguyên. Trước khi sử dụng cursor, hãy xem xét xem có cách thức nào khác có thể thực hiện nhiệm vụ tương tự mà không ảnh hưởng đến hiệu suất của cơ sở dữ liệu.