Trigger
Trigger
Chương 8
TRIGGER
Mục tiêu
Sau khi học xong chương này, SV có thể:
Biết Trigger là gì và khi nào sử dụng Trigger.
Nắm được các loại Trigger.
Nắm vững cú pháp tạo, xóa và cập nhật Trigger.
Tạo được Trigger khi thêm, xóa và cập nhật dữ liệu.
1
30/6/2023
Trigger là gì?
Trigger là một Stored Procedure không có tham số.
Trigger thực thi một cách tự động khi một trong ba câu lệnh Insert, Update, Dele
2
30/6/2023
3
30/6/2023
4
30/6/2023
Tạo Trigger
Cú pháp:
CREATE TRIGGER Tên_Trigger ON Tên_bảng
{ INSTEAD OF | FOR | AFTER } { INSERT | DELETE | UPDATE } AS
Khối lệnh xử lý
10
5
30/6/2023
Quản lý Trigger
Xóa Trigger:
Cú pháp:
DROP TRIGGER Tên_Trigger
11
6
30/6/2023
13
7
30/6/2023
16
8
30/6/2023
9
30/6/2023
10
30/6/2023
11
30/6/2023
12
30/6/2023
25
26
13
30/6/2023
14
30/6/2023
30
15
30/6/2023
----------------------Funcion-----------------------------
--5. Xây dựng hàm fn_DTB_MH(@mamh) trả về điểm TB của môn học có mã số truyền vào.
go
create function fn_DTB_MH1(@mamh varchar(2))
returns float
as
begin
declare @dtb float
select @dtb=AVG(diem) from ketqua where mamh=@mamh
return @dtb
end
/*6. Xây dựng thủ tục sp_CapNhatMH có sử dụng hàm fn_DTB_MH để cập nhật lại số tiết trong bảng
MONHOC
theo các qui tắc sau: Tăng 10 tiết nếu ĐTB của SV học dưới 5.
Tăng 5 tiết nếu ĐTB của SV học từ 5 ≤ ĐTB < 7
Không tăng số tiết nếu ĐTB của SV học ≥ 7 hoặc không
có SV học.*/
go
create proc sp_Update_Sotiet7(@mamh varchar(2))
as
if @mamh is null
begin
print 'Chua nhap mon' return
end
if not exists(select * from monhoc where mamh=@mamh)
begin
print 'Khong co mon '+@mamh return
end
if not exists(select * from ketqua where mamh=@mamh)
begin
print 'Mon '+@mamh+' chua co diem' return
end
declare @dtb float, @stt int
set @dtb=dbo.fn_DTB_MH(@mamh)
if @dtb<5 set @stt=10
if @dtb>=5 and @dtb<7 set @stt=5
if @dtb>=7 set @stt=0
update monhoc set sotiet=sotiet+@stt where mamh=@mamh
print 'Mon '+@mamh+' da duoc cap nhat so tiet'
go
exec dbo.sp_Update_Sotiet7 '01'
16
30/6/2023
go
exec dbo.sp_CapNhatMH_KyTuDau '01'
go
create function fn_DanhSachSinhVien_DTB(@makh varchar(2))
returns table
as
return
select sv.masv, Hoten=hosv+' '+tensv, dtb=avg(diem)
from sinhvien sv inner join ketqua kq on sv.masv=kq.masv
where @makh = makh
group by sv.masv, tensv, hosv
go
select * from dbo.fn_DanhSachSinhVien_DTB('AV')
go
create function fn_DanhSachMonHoc(@masv varchar(3))
returns table
as
return
select mh.mamh, tenmh, diem
from monhoc mh inner join ketqua kq on mh.mamh=kq.mamh
where @masv = kq.masv
17
30/6/2023
go
select * from dbo.fn_DanhSachMonHoc('A01')
18
30/6/2023
returns table
as
return
select sv.masv, Hoten=hosv+' '+tensv, HBM=hocbong+case when avg(diem) >=7 and
avg(diem) < 8 then 500000
else 0 end
from ketqua kq inner join sinhvien sv on sv.masv=kq.masv inner join khoa kh on
kh.makh=sv.makh
where @makh = kh.makh
group by sv.masv, hosv, tensv, hocbong
go
select * from dbo.fn_LocDSSV_CapNhatHB('LS')
---------------------------Cursor----------------------
--9.Tạo một bảng tên MONHOC_1 có cấu trúc và dữ liệu dựa vào bảng
--MONHOC (chỉ lấy hai cột: MAMH, TENMH). Sau đó, sử dụng vòng lặp WHILE
--viết đoạn chương trình dùng để xóa từng dòng dữ liệu trong bảng
--MONHOC_1 với điều kiện câu lệnh bên trong vòng lặp khi mỗi lần thực hiện
--chỉ được phép xóa một dòng dữ liệu trong bảng MONHOC_1. Sau khi xóa một
--dòng thì thông báo ra màn hình nội dung “Đã xóa môn học ” + Tên môn học.
go
declare cur_sv cursor
for select mamh,tenmh
from MonHoc_01
open cur_sv
declare @mamh varchar(3), @tenmh nvarchar(50)
fetch next from cur_sv into @mamh,@tenmh
while @@FETCH_STATUS=0
begin
select mamh,tenmh
from MonHoc_01
where mamh=@mamh
delete from MonHoc_01
where mamh=@mamh
print N'Da xoa dong' + @tenmh
fetch next from cur_sv into @mamh,@tenmh
end
close cur_sv
deallocate cur_sv
--1.Duyệt cursor và xử lý hiển thị danh sách các SV gồm các thông tin: mã SV, họ
--tên SV, mã khoa, và có thêm cột tổng số môn thi.
go
declare cur_sv cursor
for select masv,hosv,tensv,makh
from sinhvien
open cur_sv
declare @masv char(3),@hosv nvarchar(15),@tensv nvarchar(7),@makh char(2),@tongsomonthi int
fetch next from cur_sv into @masv,@hosv,@tensv,@makh
while @@FETCH_STATUS=0
begin
select @tongsomonthi =isnull(count(mamh),0) from ketqua
where masv=@masv
print @masv +@hosv+ @tensv + @makh + cast(@tongsomonthi as nvarchar(10))
fetch next from cur_sv into @masv,@hosv,@tensv,@makh
end
19
30/6/2023
close cur_sv
deallocate cur_sv
--2.Duyệt cursor và xử lý hiển thị danh sách các môn học có thêm cột Ghi chú, biết
--rằng nếu đã có SV thi thì in ra “Đã có xxx SV thi”, ngược lại thì in ra “Chưa có SV
--thi”.
go
declare cur_sv cursor
for select mamh,tenmh
from monhoc mh
open cur_sv
declare @mamh char(2),@tenmh nvarchar(50),@ghichu int
fetch next from cur_sv into @mamh,@tenmh
while @@FETCH_STATUS=0
begin
select @ghichu=count(mamh)
from ketqua kq
where mamh=@mamh
if (@ghichu > 0)
print @mamh+' '+@tenmh+' '+ N'Da co '+ cast(@ghichu as nvarchar(10)) + ' SV thi'
else
print N'Chua co sinh vien thi'
fetch next from cur_sv into @mamh,@tenmh
end
close cur_sv
deallocate cur_sv
--3.Duyệt cursor và xử lý giảm học bổng của các SV theo các qui tắc sau:
--• Không giảm nếu ĐTB 8.5
--• Giảm 5% nếu 7.5 ≤ ĐTB < 8.5
--• Giảm 10% nếu 7 ≤ ĐTB < 7.5
go
declare cur_sv cursor
for select masv
from sinhvien
open cur_sv
declare @masv varchar(3),@tb int
fetch next from cur_sv into @masv
while @@FETCH_STATUS=0
begin
select @tb=avg(diem)
from ketqua
where masv = @masv
if @tb>=7.5 and @tb<8.5
update sinhvien set hocbong=hocbong*0.95
where masv=@masv
if @tb>=7 and @tb <7.5
update sinhvien set hocbong=hocbong*0.9
where masv=@masv
fetch next from cur_sv into @masv
end
close cur_sv
deallocate cur_sv
--SP
--1. Xây dựng Stored Procedure tên sp_KetQuaThi với tham số vào là
--mã số SV (giá trị mặc định là NULL) để hiển thị thông tin: Mã SV,
--Họ và tên, Tên môn và Điểm. Nếu không truyền vào mã số SV thì
--thủ tục sẽ liệt kê kết quả thi của tất cả các sinh viên.
go
create proc sp_KetQuaThi (@masv varchar(3) = null )
as
if @masv is null
11
0
30/6/2023
begin
select sv.masv,hosv+' '+tensv,tenmh,diem from sinhvien sv inner join ketqua kq on
kq.masv=sv.masv inner join
monhoc mh on kq.mamh=mh.mamh
return
end
if not exists (select * from sinhvien sv where masv=@masv)
begin
print N'Không có sinh viên này' + @masv
return
end
if (select count(*) from ketqua kq where masv=@masv) > 0
begin
select sv.masv,hosv+' '+tensv,tenmh,diem from sinhvien sv inner join ketqua kq on
kq.masv=sv.masv inner join
monhoc mh on kq.mamh=mh.mamh where sv.masv=@masv
return
end
else
print N'Sinh viên' +@masv +N'chưa thi môn nào'
go
exec sp_KetQuaThi 'A01'
--2. Xây dựng Stored Procedure tên sp_TongHocBongSVTheoKhoa
--với tham số vào là Tên khoa để tính tổng học bổng của các sinh
--viên thuộc khoa đó. Nếu Tên khoa không hợp lệ thì thông báo lỗi.
go
create proc sp_TongHocBongSVTheoKhoa (@tenkh nvarchar(50))
as
if not exists ( select * from khoa where tenkh=@tenkh)
begin
print N'Không có khoa này' +@tenkh
return
end
if not exists (select * from sinhvien sv inner join khoa kh on sv.makh=kh.makh where tenkh=@tenkh)
begin
print N'Khoa này' +@tenkh + N'chưa có sinh viên'
return
end
declare @tong int = 0
select @tong = sum(isnull(hocbong,0)) from sinhvien sv inner join khoa kh on sv.makh=kh.makh where
tenkh=@tenkh
if @tong = 0
begin
print N'Khoa này không có học bổng'
return
end
else
begin
print N'Tổng học bổng của khoa' +@tenkh +'là' + cast(@tong as nvarchar(10))
end
go
exec sp_TongHocBongSVTheoKhoa N'Anh Văn'
--3.Xây dựng Stored Procedure tên sp_DTB để tính điểm trung bình
--với 2 tham số vào là mã môn học và mã khoa.
go
create proc sp_DTB (@mamh varchar(2), @makh varchar(2))
as
11
1
30/6/2023
go
exec sp_DTB '01','LS'
--4.Xây dựng Stored Procedure tên sp_HienThi_DSSV_TheoKhoa với
--tham số vào là mã khoa để hiển thị thông tin sinh viên thuộc Khoa
--đó và có thêm cột GHI CHÚ hiển thị “Đã thi xxx môn” nếu SV có kết
--quả thi, ngược lại thì hiển thị “Chưa có kết quả thi” nếu SV chưa thi
--môn nào.
go
create proc sp_HienThi_DSSV_TheoKhoa (@makh varchar(2))
as
if not exists (select * from khoa kh where makh = @makh)
begin
print N'Không tồn tại khoa ' +@makh
return
end
if (select count (*) from sinhvien sv where makh = @makh)>0
begin
select * , ghichu = (case when count(*) > 0 then 'Đã thi ' + count(*) +'môn'
else 'Chưa có kết quả thi' end )
from sinhvien sv inner join ketqua kq on sv.masv = kq.masv
end
go
exec sp_HienThi_DSSV_TheoKhoa 'AV'
--5.Xây dựng Stored Procedure tên sp_Them_SV để thêm 1 SV mới,
--cần kiểm tra ràng buộc dữ liệu trước khi thực hiện lệnh thêm
go
create proc sp_Them_SV (@masv varchar(2) ,@hosv nvarchar(50),@tensv nvarchar(50) ,@phai int=0,@ngaysinh
datetime,@noisinh nvarchar(50),@makh varchar(2) ,@hocbong int = 0)
as
if exists (select * from sinhvien sv where masv=@masv)
begin
11
2
30/6/2023
--1.Cho biết học bổng trung bình của SV khoa Tin Học là bao nhiêu?
--Nếu lớn hơn 100,000 thì in ra “không tăng học bổng”, ngược lại in ra “nên tăng học bổng”
go
if exists(select * from sinhvien sv inner join khoa kh on sv.makh=kh.makh where tenkh= N'Tin Học')
begin
declare @tb int
select @tb=avg(isnull(hocbong,0)) from sinhvien sv inner join khoa kh on sv.makh=kh.makh where
tenkh= N'Tin Học'
if @tb > 100000
print 'HBTB: '+ cast(@tb as varchar(10)) + N' Không tăng học bổng'
else
print 'HBTB: '+ cast(@tb as varchar(10)) + N' Nên tăng học bổng'
end
else
print N'Không có sinh viên khoa Tin Học'
--2.Sử dụng hàm DATENAME để tính xem có SV nào sinh vào ngày chủ
--nhật không? Nếu có thì in ra danh sách các SV đó, ngược lại thì in ra
--chuỗi “Không có SV nào sinh vào ngày Chủ Nhật”
go
if exists(select * from sinhvien sv where DATENAME(weekday,ngaysinh)='Sunday')
begin
select * from sinhvien sv where DATENAME(weekday,ngaysinh)='Sunday'
end
else print N'Không có SV nào sinh vào ngày Chủ Nhật'
--3.Hãy cho biết SV có mã số A01 đã thi bao nhiêu môn, nếu có thì in ra
--“SV A01
--đã thi xxx môn”, ngược lại thì in ra “SV A01 chưa có kết quả thi”
go
if exists(select * from sinhvien sv where masv='A01')
begin
declare @somonthi tinyint
select @somonthi=count(*) from ketqua kq where masv='A01'
if @somonthi>1
print N'SV A01 đã thi '+cast(@somonthi as varchar(10))+ N' môn'
else
print N'SV A01 chưa có kết quả thi'
end
else
print N'Không tồn tại sinh viên có mã A01'
--4.Hãy cho biết SV có mã số A01 đã thi đủ tất cả các môn chưa, nếu có thì
---in ra “SV A01 đã thi đủ tất cả các môn”, ngược lại thì in ra “SV A01
11
3
30/6/2023
11
4
30/6/2023
--=======================Trigger=================================--
alter table khoa add SOSV int
select * from khoa
update khoa set SOSV=(select count(*) from sinhvien where khoa.makh=sinhvien.makh)
go
delete sinhvien where masv = 'A09'
select * from sinhvien
select * from khoa
11
5
30/6/2023
*/
go
create trigger tg_UpdateSV_SOSV on sinhvien
for update
as
if update(masv)
begin
raiserror('Khong duoc sua khoa chinh', 16, 1)
rollback
return
end
--DTB, SOTC
/*create trigger tg_InsertKQ_DTB_SOTC on ketqua
for Insert
as
*/
go
create trigger tg_InsertKQ_DTB_SOTC on ketqua
for Insert
as
declare @masv char(3), @mamh char(2), @diem real
select @masv=masv, @mamh=mamh, @diem=diem from
if @diem>=5
begin
declare @sotiet int
select @sotiet = sotiet from monhoc where @mamh=mamh
update sinhvien set SOTC=SOTC-@sotiet/15 where @masv=masv
end
/*create trigger tg_UpdateKQ_DTB_SOTC on ketqua
for Update
as
*/
go
create trigger tg_UpdateKQ_SOTC_DTB on ketqua
for update
as
if update(masv) or update(mamh)
begin
raiserror('Khong duoc sua khoa chinh', 16, 1)
rollback
return
end
11
6
30/6/2023
update sinhvien set DTB=(select avg(diem) from ketqua where masv=@masv) where masv=@masv
11
7