1. Trang chủ
  2. » Luận Văn - Báo Cáo

tìm hiểu về con trỏ trong sql server

19 1,4K 3

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 19
Dung lượng 447,1 KB

Nội dung

TÌM HIỂU VỀ CON TRỎ TRONG SQL SERVERI.Tìm hiểu chung 1.1 Giới thiệu về con trỏ Khái niệm Cursor - Là một cấu trúc dữ liệu ánh xạ đến một tập các dòng dữ liệu kết quả của một câu truy vấn

Trang 1

TÌM HIỂU VỀ CON TRỎ TRONG SQL SERVER

I.Tìm hiểu chung

1.1 Giới thiệu về con trỏ

Khái niệm Cursor

- Là một cấu trúc dữ liệu ánh xạ đến một tập các dòng dữ liệu kết quả của một câu truy vấn (select)

- Cho phép duyệt tuần tự qua tập các dòng dữ liệu và đọc giá trị từng dòng

- Thể hiện của cursor là 1 biến, nhưng tên biến này không bắt đầu bằng

’@’

- Vị trí hiện hành của cursor có thể được dùng như điều kiện trong mệnh

đề where của lệnh update hoặc delete: cho phép cập nhật/xoá dữ liệu (dữ liệu thật sự trong CSDL) tương ứng với vị trí hiện hành của cursor

Một con trỏ là một đối tượng cơ sở dữ liệu được sử dụng bởi ứng dụng

để thao tác với các hàng dữ liệu thay vì các tập hợp dữ liệu Sử dụng con trỏ, nhiều tác vụ có thể được thực hiện theo từng hàng trên tập kết quả

mà có thể cần hoặc không cần sự có mặt của bảng gốc Hay nói một cách khác, con trỏ,về mặt khái niệm, trả về một tập hợp kết quả dựa trên các bảng bên trong cơ sở dữ liệu Với con trỏ chúng ta có thể :

 Cho phép định vị các hàng chỉ định của tập kết quả

 Nhận về một hàng đơn hoặc tập hợp các hàng từ vị trí hiện tại của tập kết quả

 Hỗ trợsửa đổi dữ liệu của hàng ở vị trí hiện tại trong tập kết quả

 Hỗ trợ nhiều cấp độ quan sát đối với các thay đổi được tạo ra bởi các người dùng khác trên các dữ liệu của tậpkếtquả

Trang 2

 Cung cấp các lệnh Transact-SQLtrong các script, thủ tục lưu, và bẫy lỗi để truy nhập dữ liệu trong tập kết quả

1.2 Ý nghĩa

Truy xuất đến tập bản ghi và thực hiện các thao tác do người lập trình xử

lý một số yêu cầu

Xử dụng con trỏ để thực hiện trên từng bản ghi

II.Thao tác trên con trỏ

2.1 Cú pháp

Lệnh declare được sử dụng để tạo một con trỏ Nó chứa lệnh SELECT để

bao gồm các bản ghi từ bảng Có thể sử dụng cú pháp chuẩn SQL 92 hoặc

cú pháp T_SQL mở rộng

− Cú pháp SQL 92 chuẩn:

Declare cursor_name [Insensitive] [Scroll] Cursor

For select_statement

[ For {Read only| Update [of column_name [,…n] ] }]

− Cú pháp T_SQL mở rộng

Declare cursor_name Cursor

[ Local | Global ]

[ Forward_only| Scroll] [ Static| Dynamic]

[ Read_only]

For select_statement

[ For Update [ of column_name [,…n] ] ]

Các thuộc tính được giải nghĩa dưới đây:

Local

Trang 3

Chỉ ra phạm vi hạn chế của con trỏ trong thủ tục hoặc bẫy lỗi Hay nói một cách khác, tên của con trỏ là hợp lệ bên trong phạm vi của nó Con trỏ hoàn toàn được giải phóng khi thủ tục lưu trữ hoặc bẫy lỗi bị hủy

bỏ cursor cục bộ, chỉ có thể sử dụng trong phạm vi một khối (query batch) hoặc một thủ tục/ hàm

GLobal

Chỉ ra rằng phạm vi của con trỏ là toàn cục Tên con trỏ có thể được tham chiếu trong bất cứ thủ tục lưu trữ nào Cursor toàn cục, có thể sử dụng trong một thủ tục/hàm hay một query batch bất kỳ hoặc đến khi bị hủy một cách tường minh

Forward_only

Chỉ ra rằng con trỏ chỉ có thể được duyệt từ hàng đầu tiên đến hàng cuối cùng, chế độ này chỉ hỗ trợ tuỳ chọn FETCH NEXT để lấy dữ liệu

Ngầm định con trỏ luôn ở chế độ Forward_only, cursor chỉ có thể duyệt

một chiều từ đầu đến cuối

Scroll

Chỉ ra rằng tất cả các tuỳ chọn để lấy dữ liệu (First,Last, Prior, next, Relative, Absolute) đều được hỗ trợ Nếu Scroll không được chỉ ra trong khai báo con trỏ, nó chỉ hỗ trợ tuỳ chọn NEXT, có thể duyệt lên xuống cursor tùy ý (duyệt theo đa chiều)

Static

Định nghĩa một con trỏ mà sẽ tạo ra môt bản sao của dữ liệu để sử dụng

Tất cả các yêu cầu gửi đến con trỏ được trả lời từ bảng tạm thời tempdb

Vì vậy ,việc sửa đổi dữ liệu trên các

bảng cơ sở không ảnh hưởng tới dữ liệu trả về bởi con trỏ ,và con trỏ này không cho phép sửa đổi

Trang 4

Chỉ ra thứ tự của các hàng trong con trỏ là cố định khi con trỏ được mở

Dynamic

Định nghĩa một con trỏ mà ánh xạ toàn bộ thay đổi đối với các hàng trong tập kết quả mỗi khi con trỏ duyệt trong thời gian tồn tại, nội dung của cursor có thể thay đổi nếu dữ liệu trong các bảng liên quan có thay đổi

Fast_forward

Chỉ định con trỏ là FORWARD_ONLY và READ_ONLY

FAST_FORWARD không thể được xác định bởi tuỳ chọn SCROLL hoặc FOR_UPDATE Các con trỏ FORWARDONLY và

FAST_FORWARD là loại trừ lẫn nhau

Read_only

Nghiêm cấm việc cập nhật thông qua con trỏ này Nó không thể được tham chiếu trong mệnh đề WHERE CURRENT OF trong câu lệnh

UPDATE hoặc DELETE chỉ có thể đọc từ cursor, không thể sử dụng cursor để update dữ liệu trong các bảng liên quan (ngược lại với “for update…” )

Scroll_locks

Chỉ ra rằng việc cập nhật hoặc xoá các vị trí thông qua con trỏ được đảm bảo thành công SQL Server khoá các hàng mà chúng đang được đọc vào trong con trỏ để đảm bảo khả năng sẵn sàng của chúng cho việc sửa đổi sau này Tuỳ chọn SCROLL_LOCKS không thể được xác định cùng vớiFAST_FORWARD

Optimistic

Trang 5

Chỉ ra rằng việc cập nhật hoặc xoá các vị trí thông qua con trỏ không thành công, nếu hàng được cập nhật khi nó đã được đọc vào con trỏ

Type_warning

Đưa ra một thông điệp cảnh báo gửi đến người dùng nếu con trỏ ngầm chuyển đổi từ một kiểu yêu cầu sang một kiểu khác

Update [OF Column_name[, n]]

Định nghĩa các cột có thể cập nhật trong con trỏ Nếu

OFColumn_name[,…n] được sử dụng, chỉ các cột nằm trong danh sách được phép sửa đổi

Trong số các thuộc tính nêu trên DYNAMIC, STATIC, KEYSET và FORWARD_ONLY định nghĩa các đặc trưng mang tính truy xuất dữ liệu của con trỏ và số còn lại định nghĩa các đặc trưng mang tính chất chức năng của con trỏ

Insensitive/ static: Nội dung của cursor không thay đổi trong suốt thời

gian tồn tại, trong trường hợp này cursor chỉ là read only

Lưu ý: Tên cursor trong các cách khai báo không bắt đầu bằng ký tự “@”

Mặc định khi khai báo cursor nếu không chỉ ra các tùy chọn thì cursor có các tính chất:

- Global

- Forward_only

- Read only hay “for update” tùy thuộc vào câu truy vấn

- Dynamic

Trang 6

2.2 Các bước tạo một con trỏ

Một con trỏ có thể tồn tại trong nhiều trạng thái Các trạng thái khác nhau của con trỏ liên quan đến các khu vực khác nhau nơi mà chúng được tạo

ra và thực hiện Một con trỏ đơn giản được thực thi theo các bước dưới đây:

Bước 1: Mở con trỏ :

open tên con trỏ

Bước 2: Nhận về các bản ghi :

Fetch tên con trỏ

Bước 3 : Đóng con trỏ

Close tên con trỏ

Bước 4 :Giải phóng con trỏ

Deallocate tên con trỏ

Sau khi con trỏ được tạo, nó phải được mở trước khi các bản ghi được

truy xuất từ nó Lệnh Open được sử dụng để mở một con trỏ.Cú pháp là:

OPEN <Cursor_name>

Mỗi khi con trỏ được mở, các bản ghi được truy xuất từ con trỏ để hiển

thị chúng trên màn hình Lệnh Fetch được sử dụng để hiển thị các bản

ghi từ con trỏ Cú pháp là:

Fetch <Cursor_name>

Một cách tuỳ ý, một con trỏ có thể được đóng tạm thời khi nó không cần

thiết sử dụng lệnh Close Lệnh này đóng con trỏ đang mở bằng cách

giải phóng tập kết quả hiện tại Mỗi khi con trỏ được đóng, các hàng chỉ

có thể được truy xuất sau khi mở lại nó Cú pháp là:

Close <Cursor_name>

Trang 7

Khi con trỏ không cần thiết thêm nữa, tham chiếu đến nó được huỷ bỏ Lệnh

Deallocate sử dụng để giải phóng tham chiếu tới con trỏ Cú pháp là:

Deallocate<Cursor_name>

Mỗi khi con trỏ đựoc tạo và mở, các hàng được truy xuất từ con trỏ Chúng ta sẽ xem chi tiết về việc duyệt và nhận về dữ liệu ở chương tiếp

2.3 Truy xuất và duyệt con trỏ

Khi con trỏ được mở, hàng ở vị trí hiện tại của con trỏ về mặt logic ở trước hàng đầu tiên Các con trỏ Transact-SQL có thể truy xuất một hàng tại một thời điểm Các tác vụ để nhận về các hàng từ con trỏ được gọi là

fetching Có rất nhiều thao tác truy xuất:

 FETCH FIRST:Truy xuất hàng đầu tiên

 FETCH NEXT:Truy xuất hàng tiếp theo hàng truy xuất trước đó

 FETCH PRIOR: Truy xuất hàng trước hàng truy xuất trước đó

 FETCH LAST:Truy xuất hàng cuối cùng

FETCH ABSOLUTE n:Nếu n là một số nguyên dương, nó sẽ truy xuất n hàng trong con trỏ.

Nếu n là một số nguyên âm, n hàng trước hàng cuối cùng trong con trỏ được truy xuất Nếu n bằng 0 thì không hàng nào được truy xuất.

Vídụ, FETCH Absolute 2 sẽ hiển thị bản ghi thứ hai của một bảng

FETCH RELATIVE n:Truy xuất n hàng từ hàng truy xuất trước đó, nếu

n là số dương Nếu nlà sốâm, n hàng trước hàng truy xuất trước đó được truy xuất Nếu n bằng 0, hàng hiện tại được nhận về.

Trạng thái của mỗi lệnh truy xuất có thể được xác định bởi hai biến toàn cục

Trang 8

@@FETCH _STATUS

Biếnnày trảvề một sốnguyênbiễudiễnkết quảcủalệnhtruy

xuấtcuốicùngcủacontrỏ

@@CURSOR_ROWS

Biến này trả về tổng số hàng hiện tại trong con trỏ đang mở

Hình11.8 Hiển thị một ví dụ về việc sử dụng con trỏ, và các hàng của nó được truy xuất cho đến khi biến bằng 0

Tạo con trỏ FORWARD_ONLY (Chỉtiến)

Chúng ta khai báo một con trỏ FORWARD_ONLY để thay đổi dữ liệu

của chính nó Con trỏ này bao gồm tất cả các bản ghi của bảng jobs mà

có giá trị của trường min_lvl= 75 Sau đó thay đổi giá trị cột max_lvl

của bản ghi đầu tiên= 100 Thực hiện đoạn lệnh sau ở trong Query

Analyzer :

Trang 9

DECLARE JobsCursor CURSOR FORWARD_ONLY

FOR

SELECT * FROM jobs WHERE min_lvl = 75

FOR UPDATE

OPEN JobsCursor

FETCH JobsCursor

UPDATE jobs

SET max_lvl = 100 WHERE CURRENT OF JobsCursor WHERE CURRENT OF Cursor2

SELECT * FROM jobs WHERE min_lvl = 75

CLOSE JobsCursor

DEALLOCATE JobsCursor.( Kết quả được hiển thị ở hình 2 )

Hình 2 : Ví dụ về con trỏ FORWARD_ONLY

Trang 10

Câu lệnh FETCH hiển thị nguyên bản bản ghi đầu tiên của con trỏ

Trường Max_lvl đã được thay đổi giá trị ở bản ghi đầu tiên, và sau đó

câu lệnh SELECT hiển thị giá trị đã thay đổi đó

Tạo contrỏREAD_ONLY(chỉđọc)

Bây giờ chúng ta tạo ra một con trỏ READ_ONLY, nó bao gồm các

hàng của bảng pub_info, các hàng này phải có giá trị của trường pub_id

nằm trong khoảng 1000 đến 2000 Sau đó chúng ta sẽ thử xóa một hàng của con trỏ này và xem kết quả của nó

Thực hiện đoạn lệnh sau:

DECLARE PubInfo Cursor CURSOR READ_ONLY

FOR

SELECT * FROM pub_info

WHERE pub_id between 1000 and 2000

OPEN PubInfo Cursor

FETCH PubInfo Cursor

DELETE FROM pub_info

WHERE CURRENT OF PubInfo Cursor

CLOSE PubInfo Cursor

DEALLOCATE PubInfo Cursor

Lệnh DELETE trả về một lỗi được hiển thị trong hình 3

Trang 11

Hình 3:Ví dụ về con trỏ READ_ONLY

Chú ý :

Trước khi lập trình con trỏ ta phải khai báo con trỏ bằng câu lệnh : declare tên con trỏ cursor

For [câu lệnh select]

2.4 Biến cursor

Ta có thể khai báo một biến kiểu cursor và gán cho nó tham chiếu đến một cursor đang tồn tại

Biến cursor có thể được xem như là con trỏ cursor

Biến cursor là một biến cục bộ

Biến cursor sau khi gán giá trị được sử dụng như một cursor thông thường

Ví dụ :

Trang 12

set @cur_var = my_cur

my_cur là một cursor đang tồn tại

hoặc:

Declare @cur_var cursor

set @cur_var = cursor for select_statement

Kết hợp cursor với stored procedure

Xây dựng SP tính điểm trung bình và xếp loại cho sinh viên thuộc lớp cho trước Giả sử có các quan hệ như sau:

SinhVien (MaSV, HoTen, DTB, XepLoai, Lop)

MonHoc (MaMH, TenMH)

KetQua (MaMH, MaSV, LanThi, Diem)

Biết rằng

Điểm thi chỉ tính lần thi sau cùng

Xếp loại: Xuất sắc [9, 10], Giỏi [8, 8.9], Khá [7, 7.9], Trung bình [5.0, 6.9], Yếu[0, 4.9]

Kết quả ghi xuống CSDL, đồng thời xuất ra tổng số sinh viên xếp loại giỏi của lớp đó

•Phân tích ví dụ:

Lớp cần xét có nhiều sinh viên, từng sinh viên cần được xử lý thông qua

3 bước:

Tính điểm trung bình cho sinh viên, điểm trung bình phải là điểm của lần thi sau cùng Có thể tái sử dụng thủ tục XepLoaiSVLop

Dựa vào điểm trung bình của sinh viên để xác định xếp loại

Cập nhật điểm và xếp loại vào bảng sinh viên

Trang 13

Mọi sinh viên đều lặp lại 3 bước trên Từ phân tích trên ta thấy:

Cần xử lý nhiều phần tử (các sinh viên)

Mỗi phần tử xử lý tương đối phức tạp (truy vấn, tính toán, gọi thủ tục khác, điều kiện rẽ nhánh, cập nhật dữ liệu, …)

Cách xử lý các phần tử là như nhau

⇒ Sử dụng cursor là thích hợp

Cursor chứa các sinh viên của lớp cần xét, chỉ cần chứa mã sinh viên là được

• Xây dựng thủ tục

Create procedure XepLoaiSVLop

@Lop nvarchar(10), @SoSVGioi int out

As

Declare @DTB float

Declare @XepLoai nvarchar(20) Declare @MaSV nvarchar(10) Declare cur_SV cursor

For (select MaSV from SinhVien where Lop=@Lop) Open cur_SV Fetch Next from cur_SV into @MaSV While @@FETCH_STATUS = 0 Begin

End

Exec XepLoaiSV @MaSV, @DTB output, @XepLoai output Update SinhVien set DTB = @DTB, XepLoai=@XepLoai

Where MaSV= @MaSV

Fetch Next from cur_SV into @MaSV

Close cur_SV Deallocate cur_SV

Trang 14

Set @SoSVGioi = (select count(*) from sinhvien

where lop = @Lop and XepLoai = N’Giỏi’)

Go

Từ những kiến thức chung về cursor áp dụng thực hiện một số bài toán

2.5 Ví dụ minh họa

Ví dụ 1:

Tạo ra con trỏ có tên là cur_sv chứa tập bản ghi về thông tin sinh viên Hãy duyệt tất cả các bản ghi về thông tin sinh viên đó và hiển thị kết quả

ra màn hình

Declare cur_sv cursor

For (select * from sinhvien)

Mở con trỏ

Open cur_sv

Đặt giá trị khởi đầu cho con trỏ

Fetch first from cur_sv

-Duyệt tất cả các bản ghi của con trỏ

While (@@Fetch_status=0)

-Duyệt bản ghi tiếp theo

Fetch next from Cur_sv

-Đóng con trỏ

Close cur_sv

Giải phóng con trỏ

Deallocate cur_sv

Trang 15

Ví dụ 2 :

Tạo hai biến Masv và hoten , hiển thị thông tin của sinh viên thông qua hai biến của masv và hoten đó (coi như đã có bảng sinh viên)

Declare @masv varchar (10)

Declare @hoten nvarchar (50)

Declare @cur_sv cursor

For (select masv, hoten from sinhvien )

Open cur_sv

Fetch next from cur_sv into @masv, @hoten

While @@ Fetch_status =0

Fetch next from cur_sv into @masv, @hoten

Close cur_sv

Deallocate cus_sv

Ví dụ 3

Thêm cột xếp loại rồi cập nhật giá trị cho bảng xếp loại với các thông số tương ứng là: gioi>=8, 7<= kha <8, 5 < = trung bình <7, yếu < 5

Thêm cột xếp loại

alter table ketqua

add xeploai varchar(20)

Thực hiện yêu cầu bài toán

declare @masv varchar(10)

declare @madt varchar(10)

declare @xeploai varchar(20)

Trang 16

Tạo con trỏ

declare cur_sv cursor

for select masv, madt,diem from ketqua

Mở con trỏ

open cur_sv

Duyệt bản ghi đầu tiên

fetch next from cur_sv into @masv, @madt, @diem Kiểm tra điều kiện xem có bản ghi hay không ? while(@@fetch_status=0)

begin

Câ lệnh rẽ nhánh

if @diem <5

set

@xeploai='yeu'

if @diem>=5 and @diem<7

set

@xeploai ='Trung binh'

if @diem>=7 and @diem<8

set

@xeploai='Kha'

if @diem>= 8

set

@xeploai='gioi'

Trang 17

Thực hiện công việc yêu cầu của bài toán

update ketqua

set

xeploai=@xeploai

where masv=@masv and madt=@madt

Duyệt bản ghi tiếp theo

fetch next from cur_sv into @masv, @madt, @diem

end

Ví dụ 4

Bổ sung thêm cột số lượng vào bảng đề tài , viết thủ tục lưu trữ để cập nhật cột số lượng của đề tài bằng số sinh viên tham gia đề tài đó ( Kết hợp thủ tục vào con trỏ )

Thêm cột số lượng vào bảng đề tài

alter table detai

add soluong int

Tạo ra bảng ảo chứa số lượng sinh viên của mỗi đề tài

declare @madt varchar(10)

declare @soluong int

declare cur_sosv cursor

for select madt,count(masv) from sinhvien_detai group by madt

-Mở con trỏ

OPEN cur_sosv

Duyệt bản ghi đầu tiên

Trang 18

fetch next from cur_sosv into @madt,@soluong

Kiểm tra điều kiện có bản ghi không ?

while(@@fetch_status =0)

begin

update detai

set

soluong=@soluong

where madt=@madt

Trường hợp nếu có đề tài mà chưa có sinh viên nào thực hiện update detai

set

soluong=0

where madt not in (select madt from sinhvien_detai)

Duyệt các bản ghi tiếp theo

fetch next from cur_sosv into @madt,@soluong

end

Đóng con trot

close cur_sosv

Giải phóng con trỏ

deallocate cur_sosv

Ngày đăng: 19/11/2014, 18:12

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w