You are on page 1of 13

Họ Tên: Trần Quốc Bảo

MSSV: 20521110

Bài Thực Hành Số 2


A. Stored Procedureds với tham số đầu vào
1. Tham số vào là MSGV, TENGV, SODT, DIACHI, MSHH, NAMHH. Trước
khi insert dữ liệu cần kiểm tra MSHH đã tồn tại trong table HOCHAM
chưa, nếu chưa thì trả về giá trị 0.

2. Tham số vào là MSGV, TENGV, SODT, DIACHI, MSHH, NAMHH. Trước


khi insert dữ liệu cần kiểm tra MSGV trong table GIAOVIEN có trùng
không, nếu trùng thì trả về giá trị 0.
3. Giống (1) và (2) kiểm tra xem MSGV có trùng không? MSHH có tồn tại
chưa? Nếu MSGV trùng thì trả về 0. Nếu MSHH chưa tồn tại trả về 1, ngược
lại cho insert dữ liệu.

4. Đưa vào MSDT cũ, TENDT mới. Hãy cập nhật tên đề tài mới với mã đề tài
cũ không đổi nếu không tìm thấy trả về 0, ngược lại cập nhật và trả về 1.

5. Tham số đưa vào MSSV, TENSV mới, DIACHI mới thủ lục dùng để cập
nhật sinh viên trên, nếu không tìm thấy trả về 0, ngược lại cập nhật và trả về.
B. STORED PROCEDUREDS VỚI THAM SỐ VÀO VÀ RA

1. Đưa vào TENHV trả ra: Số GV thỏa học vị, nếu không tìm thấy trả về 0.

2. Đưa vào MSDT cho biết: Điểm trung bình của đề tài, nếu không tìm thấy trả
về 0.
3. Đưa vào TENGV trả ra: SDT của giáo viên đó, nếu không tìm thấy trả về 0.
Nếu trùng tên thì có báo lỗi không? Tại sao? Làm sao để hiện thông báo có bao
nhiêu giáo viên trùng tên và trả về các SDT.

• Nếu dùng một biến nvarchar thì sẽ báo lỗi, vì nvarchar không thể lưu được
nhiều SDT mà chỉ lưu một SDT, để thông báo có bao nhiêu SDT trùng thì ta
sẽ trả ra một cursor và đêm số lượng giáo viên có tên trùng và xuất ra.
4. Đưa vào MSHD cho biết: Điểm trung bình các đề tài của hội đồng đó.
5*. Đưa vào TENGV cho biết: Số đề tài hướng dẫn, số đề tài phản biện do giáo
viên đó phụ trách. Nếu trùng tên thì có báo lỗi không hay hệ thống sẽ đếm tất cả
các đề tài của những giáo viên trùng tên đó?
C. TRIGGER

1. Tạo Trigger thỏa mãn điều kiện khi xóa một đề tài sẽ xóa các thông tin liên quan.
create or alter trigger XoaDeTai on DETAI for DELETE
as
begin
-- Nếu bảng DETAI không có dòng dữ liệu nào --
if(@@ROWCOUNT=0)
begin
-- thông báo --
print N'Lỗi. Bảng DETAI không chứa dữ liệu.'
return
end
-- Nếu có dữ liệu --
else
begin
-- Xóa dữ liệu trong bảng SV_DETAI --
Delete SV_DETAI
from SV_DETAI t1, deleted t2
where t1.MSDT=t2.MSDT
-- Xóa dữ liệu trong bảng GV_HDDT --
Delete GV_HDDT
from GV_HDDT t1, deleted t2
where t1.MSDT=t2.MSDT
-- Xóa dữ liệu trong bảng GV_PBDT --
Delete GV_PBDT
from GV_PBDT t1, deleted t2
where t1.MSDT=t2.MSDT
-- Xóa dữ liệu trong bảng GV_UVDT --
Delete GV_UVDT
from GV_UVDT t1, deleted t2
where t1.MSDT=t2.MSDT
-- Xóa dữ liệu trong bảng HOIDONG_DT --
Delete HOIDONG_DT
from HOIDONG_DT t1, deleted t2
where t1.MSDT=t2.MSDT
-- thông báo xóa thành công --
print N'Đã xóa dữ liệu thành công'
end
end

2. Tạo Trigger thỏa mãn ràng buộc là một hội đồng không quá 10 đề tài. Dùng “Group
by” có được không? Giải thích.

create or alter trigger GioiHanDeTai on HOIDONG_DT for insert,update


as
begin
-- Kiểm tra đề tài tại hội đồng có quá 10 hay không --
if( select count(t1.MSDT)
from HOIDONG_DT t1, inserted t2
where t1.MSHD=t2.MSHD) > 10
begin
-- Không cho phép chèn --
print N'Lỗi!!! Mỗi hội đồng không quá 10 đề tài.'
-- Trở về trạng thái ban đầu --
rollback transaction
end
else
print N'Thực hiện thành công'
end;

--Group by
create or alter trigger GioiHanDeTai_GB on HOIDONG_DT for insert, update
as
begin
-- Kiểm tra đề tài tại hội đồng có quá 10 hay không --
if exists (select count(t1.MSDT)
from HOIDONG_DT t1, inserted t2
where t1.MSHD=t2.MSHD
group by t1.MSHD
having count(t1.MSHD)>10)
begin
-- Không cho phép chèn --
print N'Lỗi!!! Mỗi hội đồng không quá 10 đề tài.'
-- Trở về trạng thái ban đầu --
rollback transaction
end
else
print N'Thực hiện thành công'
end
3. Tạo Trigger thỏa mãn ràng buộc là một đề tài không quá 3 sinh viên. Dùng “Group
by” có được không? Giải thích.
create or alter trigger GioiHanSinhVienDeTai on SV_DETAI for insert, update
as
begin
if (select count(t1.MSSV)
from SV_DETAI t1, inserted t2
where t1.MSDT = t2.MSDT) > 3
begin
-- Không cho phép thêm --
print N'Lỗi!!! Mỗi đề tài không quá 3 sinh viên.'
rollback transaction
end
else
print N'Thực hiện thành công'
end

-- Group by
create or alter trigger GioiHanSinhVienDeTai_GB on SV_DETAI for insert, update
as
begin
-- Kiểm tra đề tài tại hội đồng có quá 10 hay không --
if exists (select count(t1.MSSV)
from SV_DETAI t1, inserted t2
where t1.MSDT=t2.MSDT
group by t1.MSDT
having count(t1.MSSV)>3)
begin
-- Không cho phép thêm --
print N'Lỗi!!! Mỗi đề tài không quá 3 sinh viên.'
rollback transaction
end
else
print N'Thực hiện thành công'
end

4. Tạo Trigger thỏa mãn ràng buộc là một giáo viên muốn có học hàm PGS phải là tiến
sĩ.
create or alter trigger HocHam_GV on GIAOVIEN for insert, update
as
begin

if exists ( select *
from GV_HV_CN t1, inserted t2
where t1.MSGV=t2.MSGV
and t1.MSHV!=4
and t2.MSHH=1 )
begin
print N'Phó giáo sư phải có học vị tiến sĩ'
rollback transaction
end
else
print N'Thực hiện thành công'
end
-- Bảng GV_HV_CN
create or alter trigger HocHam_GV_HV_CN on GV_HV_CN for insert, update
as
begin

if exists ( select *
from GIAOVIEN t1, inserted t2
where t1.MSGV=t2.MSGV
and t2.MSHV!=4
and t1.MSHH=1 )
begin
print N'Phó giáo sư phải có học vị tiến sĩ'
rollback transaction
end
else
print N'Thực hiện thành công'
end

D. FUNCTION

1. Viết hàm tính điểm trung bình của một đề tài. Giá trị trả về là điểm trung bình ứng
với mã số đề tài nhập vào
create or alter function DiemTB_Detai (@msdt char(6))
returns float
as
begin
declare @diemTB float = 0, @tongdiem float = 0, @tongGV float
= 0
-- Tính tổng số điểm của GV chấm và tổng số GV đã chấm ở bảng
GV_HDDT:
if(exists(select * from GV_HDDT where MSDT=@msdt))
begin
select @tongdiem=SUM(DIEM)+@tongdiem, @tongGV=COUNT(*)+@tongGV
from GV_HDDT
where MSDT=@msdt
end
-- Tính tổng số điểm của GV chấm và tổng số GV đã chấm ở bảng
GV_PBDT:
if(exists(select * from GV_PBDT where MSDT=@msdt))
begin
select @tongdiem=SUM(DIEM)+@tongdiem, @tongGV=COUNT(*)+@tongGV
from GV_PBDT
where MSDT=@msdt
end
-- Tính tổng số điểm của GV chấm và tổng số GV đã chấm ở bảng
GV_UVDT:
if(exists(select * from GV_UVDT where MSDT=@msdt))
begin
select @tongdiem=SUM(DIEM)+@tongdiem, @tongGV=COUNT(*)+@tongGV
from GV_UVDT
where MSDT=@msdt
end
-- Tính điểm trung bình
if @tongdiem =0 set @diemTB=0
if @tongGV =0 set @diemTB=0
else
set @diemTB = @tongdiem / @tongGV

return @diemTB
end
2. Trả về kết quả của đề tài theo MSDT nhập vào. Kết quả là DAT nếu như điểm trung
bình từ 5 trở lên, và KHONGDAT nếu như điểm trung bình dưới 5.
create or alter function KetQuaDT (@msdt char(6))
returns varchar(20)
as
begin
declare @dtb float, @KetQua varchar(20)

select @dtb = (sum(distinct GV_HDDT.DIEM) + sum(distinct GV_PBDT.DIEM) +


sum(distinct GV_UVDT.DIEM)) / (count(distinct GV_HDDT.MSGV) +
count(distinct GV_PBDT.MSGV) + count(distinct GV_UVDT.MSGV))
from DETAI inner join HOIDONG_DT on HOIDONG_DT.MSDT = DETAI.MSDT
inner join GV_HDDT on GV_HDDT.MSDT = DETAI.MSDT inner join GV_PBDT on
GV_PBDT.MSDT = DETAI.MSDT
inner join GV_UVDT on GV_UVDT.MSDT = DETAI.MSDT
where DETAI.MSDT = @MSDT
group by DETAI.MSDT

if @dtb is null
set @dtb=0

if @dtb < 5
set @KetQua='KHONGDAT'
else
set @KetQua='DAT'

return @KetQua
end
3*. Đưa vào MSDT, trả về mã số và họ tên của các sinh viên thực hiện đề tài.
create or alter function SV_ThucHien_DT (@msdt char(6))
returns @temp_table TABLE (mssv char(8), tensv nvarchar(30))
as
begin

declare @c cursor, @mssv char(8), @tensv nvarchar(30)

set @c=cursor for select MSSV from SV_DETAI where @msdt=MSDT


open @c
fetch next from @c into @mssv
while @@FETCH_STATUS=0
begin
select @mssv=sv.MSSV, @tensv=TENSV from SINHVIEN sv,
SV_DETAI svdt
where MSDT=@msdt and @mssv=sv.MSSV
insert into @temp_table values (@mssv,@tensv)
fetch next from @c into @mssv
end
close @c
deallocate @c
return
end

E. CURSOR
Tạo một bảng tên là DETAI_DIEM. Cấu trúc bảng như sau:
DETAI_DIEM(MSDT, DIEMTB)
1. Viết Cursor tính điểm trung bình cho từng đề tài. Sau đó lưu kết quả vào bảng
DETAI_DIEM.

--Tạo một bảng tên là DETAI_DIEM.


drop table DETAI_DIEM
create table DETAI_DIEM
(
MSDT char(6),
DIEMTB float,
primary key(MSDT)
)

--Khai báo con trỏ với tập kết quả


declare @c = cursor for select MSDT,TENDT, DiemTB_Detai(MSDT) as DIEMTB from DETAI
declare @msdt char(6), @tendt nvarchar(30), @diemtb float

open @c
fetch @c into @msdt,@tendt,@diemtb
while @@FETCH_STATUS=0
begin
-- chèn dữ liệu ---
insert into DETAI_DIEM values (@msdt,round(@diemtb,2))
fetch next from c into @msdt,@tendt,@diemtb
end
close @c
deallocate @c

3. Gom các bước xử lý của Cursor ở câu 1 vào một Stored Procedure.
create or alter procedure XuLyCursor
as
begin
declare @c = cursor for select MSDT,TENDT, dbo.DiemTB_Detai(MSDT) as DIEMTB
from DETAI
declare @msdt char(6), @tendt nvarchar(30), @diemtb float
open @c
fetch @c into @msdt,@tendt,@diemtb
while @@FETCH_STATUS=0
begin
-- chèn dữ liệu ---
insert into DETAI_DIEM(MSDT,DIEMTB) values
(@msdt,round(@diemtb,2))
fetch next from c into @msdt,@tendt,@diemtb
end
close @c
deallocate @c
print N'Chèn dữ liệu vào bảng DETAI_DIEM thành công'
end

3*. Tạo thêm cột XEPLOAI có kiểu là NVARCCHAR(20) trong bảng


DETAI_DIEM, viết Cursor cập nhật kết quả xếp loại cho mỗi đề tài như sau:
+ "Xuất sắc": điểm trung bình từ 9 đến 10.
+ "Giỏi": điểm trung bình từ 8 đến 9.
+ "Khá": điểm trung bình từ 7 đến 8.
+ "Trung bình": điểm trung bình từ 5 đến 6
+ "Không đạt": điểm trung bình dưới 5.
-- thêm cột XEPLOAI có kiểu là NVARCCHAR(20) trong bảng DETAI_DIEM
alter table DETAI_DIEM
add XEPLOAI nvarchar(20)

declare @p = cursor for select MSDT,dbo.DiemTB_DeTai(MSDT) as DIEMTB from DETAI


declare @msdt char(6), @diemtb float
open @p
fetch @p into @msdt, @diemtb
while @@FETCH_STATUS=0
begin
if @diemtb >= 9 and @diemtb <= 10
update DETAI_DIEM set XEPLOAI=N'Xuất sắc' where @msdt=MSDT
if @diemtb >= 8 and @diemtb < 9
update DETAI_DIEM set XEPLOAI=N'Giỏi' where @msdt=MSDT
if @diemtb >= 7 and @diemtb < 8
update DETAI_DIEM set XEPLOAI=N'Khá' where @msdt=MSDT
if @diemtb >= 5 and @diemtb < 6
update DETAI_DIEM set XEPLOAI=N'Trung bình' where @msdt=MSDT
if @diemtb < 5
update DETAI_DIEM set XEPLOAI=N'Không đạt' where @msdt=MSDT
fetch next from p into @msdt,@diemtb
end
close @p
deallocate @p

You might also like