Môêt bất lợi lớn của server cursor là chúng không hỗ trợ tất cả các lêênh T-SQL cũng như không hỗ trợ các lêênh T-SQL tạo ra nhiều bôê kết quả.. Nếu sử dụng FORWARD_ONLY
Trang 1Cursor: định nghĩa và cách sử
dụng Hàm của người dùng
Trang 2Mục tiêu
1. Tạo và sử dụng cursor
2. Tạo và sử dụng hàm của người dùng
Trang 3Vai trò của Cursor
(result set) thỏa mãn các điều kiêên trong mêênh đề WHERE, cả tâêp kết quả (result
các ứng dụng cần môêt cơ chế sao cho mỗi thời điểm chỉ làm viêêc với 1 hàng
hay 1 nhóm các hàng
Chính cursor thỏa mãn cơ chế này
Trang 4Vai trò của Cursor
Cursor cho phép:
Định vị tại 1 hàng xác định trong bôô kêt qua
Khôi phục (retrieving) 1 hàng hay 1 khối hàng từ vị trí hiêôn hành trong bôô kết qua.
hô trợ viêôc chỉnh sửa dữ liêôu vào các hàng tại vị trí hiêôn hành của bôô kết qua
hô trợ các mức nhìn khác nhau đến các thay đổi
trong bôô kết qua mà các thay đổi này được thực
hiêôn bởi người dùng khác
Cung cấp các lêônh TSQL trong script, stored
Trang 5Cursor là gì?
Là 1 đối tượng của CSDL để giúp truy xuất và thao tác trên 1 bộ kết quả (result set) của lệnh truy vấn
Cursor cho phép xử lý các hàng trong bộ kết quả theo 1 trong các cách sau:
• Cho phép các hàng xác định được khôi phục từ
Trang 6Các cách tạo cursor
SQL Server™ 2000 hỗ trợ 3 cách thực thi cursor :
Transact-SQL cursors: dùng lêênh DECLARE CURSOR trong các scripts, stored procedures, và triggers Các cursors này được thực thi trên server và được điều hành bởi các lêênh T-SQL được gửi đến từ client.
Application programming interface (API) server cursors: dùng
các hàm API về cursor trong OLE DB, ODBC và DB-Library Các
cursor này được thực thi trên server Mỗi lần 1 ứng dụng client gọi hàm API cursor, thì SQL Server OLE DB provider, ODBC driver, hay DB-Library dynamic-link library (DLL) sẽ chuyển yêu cầu đến server để tạo API server cursor.
Client cursors: được thực thi nôêi bôê bởi SQL Server ODBC driver,
Trang 7Các cách tạo cursor
Vì Transact-SQL cursors và API server cursors đều được thực thi trên server, nên chúng được gọi chung lại là server cursors
Môêt bất lợi lớn của server cursor là chúng không hỗ trợ tất cả các lêênh T-SQL cũng như không hỗ trợ các lêênh T-SQL tạo ra nhiều bôê kết quả Vì vâêy chúng
không thể được dùng khi ứng dụng thực thi 1 thủ tục hay 1 batch mà chứa nhiều hơn 1 lêênh SELECT
Không sử dụng lẫn lôên các loại cursor này Nếu đã tạo cursor bằng lêênh T-SQL thì nên để măêc đinh
thuôêc tính của API cursor
Trang 8Bốn loại cursor
Các loại cursor này khác nhau về khả năng phát hiêên những biến đổi trong bôê kết quả và trong tài nguyên như bôê nhớ và dung lượng của tempdb
Khả năng phát hiêên các thay đổi của cursor cung bi ảnh hưởng bởi mức cô lâêp transaction.
1 Static cursors: ít phát hiêên thay đổi nhất và cũng ít
dùng tài nguyên nhất khi duyêêt (scrolling) bôê kết quả.
2 Dynamic cursors: phát hiêên tất cả các thay đổi nhưng tiêu tốn nhiều tài nguyên nhất.
3 Forward-only cursors
Trang 9Cấu trúc của Cursor
Các nhiệm vụ sau cần được thực hiện khi sử dụng cursor:
• Cursor cần được định nghĩa và các thuộc tính của nó cần được xác lập.
• Cursor cần được mở (open).
• Các hàng được yêu cầu cần được đọc(fetch) từ cursor.
• Dữ liệu trong hàng hiện hành của cursor có thể sửa đổi nếu cần.
• Cursor cần được đóng lại khi không dùng nữa.
• Cursor nên được giai phóng khỏi bộ nhớ sau khi đóng lại
Trang 10Lệnh khai báo cursor
DECLARE cursor_name CURSOR
Trang 11Khai báo cursor
LOCAL: phạm vi của cursor là cục bộ trong phạm
vi 1 batch, thủ tục, hay trigger trong đó cursor
được tạo ra
GLOBAL: phạm vi của cursor là tòan cục được dùng trong suốt phiên kết nối Cursor sẽ bi xóa khi mất kết nối
Trang 12Khai báo cursor
Forward-only : chỉ có thể đọc (fetch) các hàng một cách
tuần tự từ đầu đến cuối bộ kết quả Nếu sử dụng
FORWARD_ONLY mà không dùng từ khóa STATIC,
KEYSET, hay DYNAMIC thì cursor sẽ được tạo như 1
DYNAMIC cursor Khi không dùng cả FORWARD_ONLY
và SCROLL thì FORWARD_ONLY được xem như măêc đinh trừ phi có dùng các từ khóa STATIC, KEYSET, or
DYNAMIC (măêc đinh của STATIC, KEYSET, và
DYNAMIC là SCROLL) FORWARD_ONLY chỉ hỗ trợ cho các loại cursor STATIC, KEYSET, và DYNAMIC
Trang 13Khai báo cursor
Static: bộ kết quả được khôi phục và lưu trữ trong 1 bảng của CSDL tempdb Những sửa đổi được làm
trong bảng gốc sẽ không được phản ánh trong dữ liệu đọc được từ cursor và cursor này không chấp nhận bất kỳ sửa đổi nào
DYNAMIC: tạo 1 cursor phản ánh tất cả những thay đổi dữ liệu xảy ra tại các hàng trong bộ kết qủa khi di chuyển quanh các hàng trong bôê kết quả Mỗi lần đọc (fetch) môêt hàng thì có thể thay đổi gía tri, thứ tự của hàng đó
Trang 14Khai báo cursor
KEYSET: xác đinh thứ tự các hàng trong cursor là cố đinh khi cursor được mở Tâêp hợp các khóa xác đinh tính duy nhất các hàng được xây dựng trong 1 bảng của tempdb Các thay đổi vào giá tri không phải khoá ngay trong bảng gốc được thực hiện bởi người tạo cursor hay từ các người dùng khác đều có thể nhìn thấy được từ cursor khi di chuyển trong cursor Riêng lệnh insert được làm từ người dùng khác thì không thể nhìn thấy được từ cursor
Trang 15Khai báo cursor
FAST_FORWARD có nghĩa là cursor vừa
FORWARD_ONLY vừa READ_ONLY Không thể dùng FAST_FORWARD cùng với tùy chọn
SCROLL, FOR_UPDATE hay FORWARD_ONLY.
READ-ONLY: không thể cập nhật dữ liệu thông qua cursor
UPDATE [OF column_name [, n]]: xác đinh các cột có thể cập nhật bên trong cursor Nếu dùng tuỳ chọn này mà không xác đinh danh sách cột có
nghĩa là tất cả các cột đều có thể được cập nhật
Trang 16Lệnh mở cursor
Để mở cursor
OPEN cursor_name
Trang 17Đọc dữ liệu - Fetching data
Khôi phục dữ liêêu từ 1 hàng xác đinh của Transact-SQL server cursor
FETCH [[NEXT | PRIOR | FIRST | LAST |
ABSOLUTE n | RELATIVE n] ]
FROM cursor_name [ INTO @variable_name [ , n ] ]
NEXT: chuyển cursor tới hàng kế tiếp trong bộ kết quả ( mặc đinh)
PRIOR: quay về lại hàng kế trước trong bộ kết quả.
FIRST: quay về lại hàng đầu tiên
LAST: chuyển đến hàng cuối cùng trong bộ kết quả
ABSOLUTE n: chuyển đến hàng thứ n
RELATIVE n: chuyển đến hàng thứ n kể từ hàng hiện hành
Trang 18Biến @@fetch_status
Nó trả về trạng thái của lệnh fetch vừa được thực thi
Trang 19Đóng và giải phóng Cursor khỏi
Trang 20Ví dụ 1: Tạo 1 cursor đơn
FETCH NEXT FROM
authors_cursor
END CLOSE authors_cursor DEALLOCATE
Trang 21Ví dụ 2: dùng scroll và tùy chọn
Fetch the last row in the cursor.
FETCH LAST FROM
authors_cursor
Fetch the row immediately prior
to the current row in the cursor.
FETCH PRIOR FROM
Fetch the row that is two rows prior to the current row FETCH RELATIVE -2 FROM authors_cursor
CLOSE authors_cursor DEALLOCATE authors_cursor
GO
Trang 22Cursor có thể cập nhật (Updatable cursor)
Updatable cursors hỗ trợ các lêênh sửa đổi dữ liêêu cho
phép câêp nhâêt các hàng thông qua cursor Sau khi đã đinh
vi 1 hàng trong updatable cursor , có thể dùng lêênh update hay delete trên bản gốc đã dùng để tạo cursor Thao tác này được gọi là positioned updates
Positioned update được thực hiêên trên cùng kết nối với
cursor đang mở Điều này cho phép các sửa đổi dữ liêêu chia xẻ cùng 1 transaction với cursor, tránh bi cấm bởi các khóa của cursor
Có hai phương pháp để thực hiêên các positioned update trong 1 cursor:
Trang 23Cách thực thi Positioned Update bằng
lệnh T-SQL
Mêênh đề WHERE CURRENT OF được dùng trong
stored procedures, triggers và script khi cần thực
hiêên sửa đổi trên 1 hàng nào đó của cursor Trình tự trong 1 stored procedure, trigger, hay script là:
DECLARE và OPEN môôt cursor.
Dùng lêônh FETCH để định vị hàng cần chỉnh sửa trong cursor.
Thực hiêôn lêônh UPDATE hay DELETE với mêônh đề WHERE CURRENT.
Trang 24Ví dụ: lệnh DELETE xóa hàng hiện hàng của cursor
DECLARE complex_cursor CURSOR scroll
FOR SELECT cShopperId FROM dbo.Shopper
WHERE cShopperId not in
(SELECT cShopperId from dbo.Orders) OPEN complex_cursor;
FETCH absolute 5 FROM complex_cursor;
DELETE dbo.Shopper
WHERE CURRENT OF complex_cursor ;
Trang 25Ví dụ: lệnh Update dùng dữ liệu hàng hiện
INSERT INTO dbo.Table1 VALUES (1, 10);
INSERT INTO dbo.Table2 VALUES (1, 20);
INSERT INTO dbo.Table2 VALUES (2, 30);
Trang 26Cursor và thủ tục thực thi
DECLARE SampleCrsr CURSOR
FOR SELECT TOP (20) CompanyName FROM Customer
WHERE CompanyName LIKE 'S%';
Trang 27Cursor và thủ tục thực thi cursor
Trang 28Thủ tục và tham số OUTPUT là
Trang 29Thủ tục và tham số OUTPUT là
CURSOR
Thực thi 1 batch khai báo biến cursor cục bôê, thực thi thủ tục để gán output dạng cursor vào biến cục bôê
DECLARE @MyCursor CURSOR
EXEC titles_cursor @titles_cursor = @MyCursor OUTPUT
Trang 30Khóa cursor
Lêênh SELECT trong 1 cursor sẽ có cùng quy tắc khóa transaction như trong lêênh SELECT đôêc lâêp Tuy
nhiên trong cursor, có thêm bôê các khóa scroll tùy
theo mức đồng thời (concurrency) của cursor
Hai cách để kiểm soát khóa:
Xác định mức cô lâôp transaction (isolation level)
Theo các gợi ý từ mêônh đề FROM.
Các khóa này sẽ được giữ cho đến cuối transaction hiêên hành đối với cả cursor và lêênh SELECT đôêc lâêp
Trang 31GO DECLARE abc CURSOR STATIC FOR SELECT * FROM authors
GO OPEN abc
GO
Trang 32Khóa cursor
Đăêt mức cô lâêp transaction là repeatable read có nghĩa là cả hai lêênh SELECT trong hai ví dụ đều tạo ra khóa S (shared) trên mỗi hàng được đọc Khóa S sẽ được giữ cho đến khi transaction
được commit hay rollback
Trang 33Khóa cursor
Măêc dù cursor tuân theo cùng quy luâêt như lêênh SELECT đôêc lâêp, bất xét đến kể loại khóa nào đang được transaction chiếm giữ, các khóa của cursor sẽ được chiếm giữ ở những thời điểm khác nhau Các khóa loại này luôn luôn được cấp chỉ khi nào có 1 hàng được khôi phục
Tùy theo mỗi loại cursor, viêêc khôi phục các hàng được thực hiêên ở các thời điểm khác nhau
Trang 34hàng của bôê kết quả tại thời điểm mở cursor.
Dynamic cursors không khôi phục các hàng cho đến khi chúng được đọc (fetch) Khóa sẽ không chiếm giữ các hàng cho đến khi chúng được đọc
Fast forward-only cursors thay đổi khi chúng chiếm khóa
Trang 35Cursor và transaction
SQL Server hỗ trợ các tùy chọn session và database để điều khiển cursor bi đóng hay vẫn tiếp tục mở khi có lêênh commits hay rollbacks
Có thể dùng 1 trong 2 cách sau:
Dùng tùy chọn của session CURSOR_CLOSE_ON_COMMIT
Dùng tùy chọn CURSOR_CLOSE_ON_COMMIT của lêônh ALTER DATABASE
Nếu các tùy chọn này là ON, thì cursor sẽ đóng khi có lêênh commit hay rollback, khi đó tất cả khóa scroll sẽ tự đôêng được giải phóng khi cursor đóng lại
Nếu các tùy chọn này là OFF, cursor vẫn tiếp tục mở khi có lêênh
COMMIT, các khóa scroll vẫn được giữ cho đến lêênh fetch kế tiếp hay cho đến khi cursor đóng lại Tất cả các khóa transaction thâêm chí các khóa ngay trên các hàng của cursor được tự do khi transaction
commit hay rollback bất kể cursor có tiếp tục mở hay không
Trang 36Cursor và transaction
Cú pháp:
SET CURSOR_CLOSE_ON_COMMIT { ON | OFF }
Ví dụ:
Trang 37PRINT ' Declare and open cursor'
DECLARE testcursor CURSOR FOR SELECT a FROM t1
OPEN testcursor
PRINT ' Commit tran'
COMMIT TRAN
PRINT ' Try to use cursor'
FETCH NEXT FROM testcursor
Sau lệnh commit tran thi cursor cũng bị đóng
theo
Trang 38PRINT ' Declare and open cursor'
DECLARE testcursor CURSOR FOR SELECT a FROM t1 OPEN testcursor
PRINT ' Commit tran'
COMMIT TRAN
Trang 39Ví dụ
Để mời họp tất ca trưởng phòng, cần tạo 1 danh sách các phòng ban và tên trưởng phòng tương ứng theo mẫu sau:
Department Name = Production
Department Head = Samuel Moore
Department Name = Sales
Department Head = Donald Fleming
………
………
Trang 40Ví dụ
DECLARE @DepartmentName char(25)
DECLARE @DepartmentHead char(25)
DECLARE curDepartment cursor for
SELECT vDepartmentName,vDepartmentHead FROM Department
OPEN curDepartment
Trang 41Ví dụ
Thực hiện vòng lặp để hiển thi tất cả các hàng của cursor While (@@fetch_status = 0)
BEGIN
Print 'Department Name = ' + @DepartmentName
Print 'Department Head = ' + @DepartmentHead
Đọc vào hàng kế tiếp của cursor.
FETCH curDepartment into @DepartmentName,
@DepartmentHead END
Đóng cursor
CLOSE curDepartment
Giải phóng cursor khỏi bộ nhớ.
DEALLOCATE curDepartment
Trang 42Ví dụ 2
Cần hiển thi họ, tên, điểm và kết quả thi cho các ứng viên bên ngoài Nếu điểm thi bằng hay lớn hơn 90, thông báo ‘'Selected for the Interview' sẽ được hiển thi trong cột Status, ngược lại thông báo 'Not Selected for the Interview' sẽ được hiển thi trong cột status Báo cáo có dạng như sau:
First Name Last Name Marks Status
Angela Smith 80 Not Selected for the Interview Barbara Johnson 82 Not Selected for the Interview
Betty Williams 70 Not Selected for the Interview
Carol Jones 45 Not Selected for the Interview
Trang 43Ví dụ 2
DECLARE @FirstName char(25)
DECLARE @LastName char(25)
DECLARE @Mark smallint
DECLARE @Result varchar(20)
DECLARE curExternalCandidate cursor for
Trang 45Các lợi ích của hàm người
và biên dich lại
Có thể giảm nghẽn mạng
Trang 46Hàm của người dùng
User-defined Functions
Hàm của người dùng là các hàm T-SQL có thể nhận các tham số đầu vào và trả về hoặc 1 giá tri đơn
( single value) ho ặc 1 bộ giá tri ( result set) dạng bảng.
Hàm người dùng có thể có từ 0 đến 1024 tham số
ngõ vào
Hàm người dùng không có tham số ngõ ra.
Có ba loại hàm người dùng:
• Scalar – tra về giá trị đơn
• Inline table-valued – tra về 1 bang kết qua nhưng trong hàm không thể có nhiều hơn 1 lệnh.
Trang 47Scalar Function
CREATE FUNCTION [ owner_name ] function_name
( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] } [ , n ] ] )
RETURNS scalar_return_data_type
[ AS ]
BEGIN
function_body RETURN scalar_expression
END
Khi tham số của hàm có giá tri mặc đinh, để sử dụng giá tri mặc đinh thì phải dùng từ khoá DEFAULT gọi hàm ( khác với thủ tục)
Loại trả về có thể là bất kỳ dữ liệu nào ngoại trừ text, ntext, image, cursor và timestamp.
Trang 48Ví dụ
Bạn cần tạo 1 bảng City chứa chi tiết thành phố
và tiểu bang của nhân viên trong công ty Trong khi chèn các hàng vào bảng, rất khó nhớ tên tiểu bang của tất cả các thành phố Bạn cần làm đơn giản quá trình chèn sao cho tiểu bang của 1
thành phố nào đó được đưa vào bảng một cách tự động
Trang 49Tạo 1 biến lưu trữ giá tri được trả về
DECLARE @StateName varchar(30)
SELECT @StateName=case @city
when ‘Menlo Park’ then ‘CA’
when ‘Oakland’ then ‘CA’
when ‘Berkeley’ then ‘CA’
when ‘Nashville’ then ‘TN’
when ‘Rockville’ then ‘MD’
when ‘Walnut Creek’ then ‘CA’
else ‘Unknown’
end
return @StateName
Trang 50INSERT City(ccity) values (‘Oakland’)
INSERT City(ccity)