ITViec

By ITViet.net - Blog nơi chia sẻ về digital marketing, social marketing, graphic design và kỹ năng mềm, tiếng anh, việc làm cho bạn 4.5 sao trên 912người dùng

ITViec.net - Chia sẻ mọi thứ cho bạn.

Tuesday, December 30, 2014

Bài Tập View, Trigger (SQL tổng hợp)

7:00 PM By


--Thêm 1 dòng vào bảng kết quả với lần thi phải là lần thi trước đó +1 của môn học và học viên đang xét

CREATE PROC THEMMOTDONG
@MaHocVien nvarchar(50),
@MaMonHoc nvarchar(50),
@Diem float
AS
BEGIN
IF(NOT EXISTS (SELECT * FROM HOCVIEN AS HV WHERE @MaHocVien = HV.MaHocVien))
BEGIN
PRINT N'Mã học viên ' + @MaHocVien + N' không tồn tại'
RETURN -1
END
IF(NOT EXISTS (SELECT * FROM MONHOC AS MH WHERE @MaMonHoc = MH.MaMonHoc))
BEGIN
PRINT N'Mã môn học ' + @MaMonHoc + N' không tồn tại'
RETURN -1
END
if @MaHocVien in (SELECT hv.MaHocVien FROM HOCVIEN AS HV, KETQUA AS KQ WHERE HV.MaHocVien = KQ.MaHV)
BEGIN
INSERT KETQUA(MaHV, MaMonHoc,Diem)
VALUES(@MaHocVien, @MaMonHoc,@Diem)
UPDATE KETQUA SET LanThi = LanThi + 1
END

END

DECLARE @kq INT
EXEC @kq = THEMMOTDONG N'HV000001  ',N'MH00001   ',  3.5
PRINT @kq
SELECT * FROM KETQUA

-- câu 1: Cập nhâp sỉ số cho các lớp

CREATE PROC CapNhapSiSo
@siso nvarchar(50)
AS
BEGIN
DECLARE Siso CURSOR
FOR
SELECT HV.MaLop, COUNT(*) As Siso
FROM HocVien HV, LopHoc LH WHERE HV.MaLop=LH.MaLop
AND  HV.TinhTrang = N''
GROUP BY SiSo
Open Siso
DECLARE
@MaLop nvarchar(10), @ss int
FETCH NEXT FROM Siso into @MaLop, @ss
WHILE @@FETCH_STATUS=0
UPDATE LOPHOC set SiSo=@ss where MaLop=@MaLop
FETCH NEXT FROM Siso into @MaLop, @ss
END
GO
-- câu 2: Viết proc cập nhập thông tin học viên

CREATE PROC CapNhatThongTinHocVien
@MaHV nchar(10),
@TenHV nvarchar(50),
@NgaySinh datetime,
@TinhTrang nvarchar(50),
@MaLop nchar(10)
AS
BEGIN
SELECT MaHocVien FROM HOCVIEN
UPDATE HOCVIEN SET TenHocVien = @TenHV ,NgaySinh = @NgaySinh,
TinhTrang = @TinhTrang, MaLop = @MaLop WHERE MaHocVien = @MaHV

END
GO

-- Câu 3: Thêm mới 1 học viên
CREATE THEMHOCVIEN
@MAHV nvarchar(20),
@TENHV nvarchar(50),
@NGAYSINH DATETIME,
@TINHTRANG nvarchar(10),
@MALOP nchar(10)
AS
BEGIN
IF( EXISTS( SELECT * FROM LopHoc WHERE MaLop=@MALOP)
AND NOT EXISTS (SELECT * FROM HOCVIEN WHERE MaHocVien= @MAHV))
INSERT INTO HOCVIEN(MaHocVien, TenHocVien, NgaySinh, TinhTrang, MaLop)
VALUES (@MAHV, @TENHV,@NGAYSINH,@TINHTRANG,@MALOP)
UPDATE LOPHOC SET SiSo = SiSo + 1
WHERE MaLop=@MALOP
END
GO
USE QLHocVien

-- 1 Viết function tính điển trung bình của một học viên
ALTER FUNCTION f_TinhDiemTrungBinhMotHocVien (@mahocvien nchar(10))
returns float
AS
Begin
return (SELECT SUM(KQ.Diem * MH.SoChi)/SUM(MH.SoChi)
FROM KETQUA AS KQ, MONHOC AS MH
WHERE  KQ.MaMonHoc = MH.MaMonHoc AND KQ.MaHV = @mahocvien
AND LANTHI = (SELECT MAX(LANTHI)
FROM KETQUA as KQ2
WHERE KQ2.MaMonHoc = KQ.MaMonHoc AND KQ2.MaHV LIKE KQ.MaHV )
)
End
GO
select dbo.f_TinhDiemTrungBinhMotHocVien(N'HV000001') AS 'Điểm Trung Bình'

GO
SELECT * FROM HOCVIEN WHERE HOCVIEN.MaHocVien = N'HV000004  '

-- 2 . Dung cau 1, cho ds cac hoc vien (mã, tên, ĐTB)
ALTER FUNCTION f_DanhSachHV()
returns Table
AS
return(SELECT HV.MaHocVien, HV.TenHocVien, dbo.f_TinhDiemTrungBinhMotHocVien(HV.MaHocVien) as DTB
FROM HOCVIEN as HV, KETQUA as KQ
WHERE HV.MaHocVien = KQ.MaHV
GROUP BY HV.MaHocVien, HV.TenHocVien)
GO

SELECT * FROM f_DanhSachHV()
GO

-- 3 Viet Functiom tim ĐTB cao nhất lớp A
ALTER FUNCTION f_TinhDiemTrungBinhCaoNhatCuaMotLop (@malop nchar(10))
returns float
AS
Begin
DECLARE @DTBMAX float
SELECT @DTBMAX=  MAX(dbo.f_TinhDiemTrungBinhMotHocVien(HV.MaHocVien))
FROM HOCVIEN as HV, KETQUA as KQ
WHERE HV.MaLop = @malop
return @DTBMAX
End
GO
select dbo.f_TinhDiemTrungBinhCaoNhatCuaMotLop(N'LH000002') AS N'Điểm trung bình cao nhất'
-- 4 Cho danh sach cac hoc vien co ĐTB cao nhất của lớp A

CREATE FUNCTION f_DanhSachHocVienDiemCaoNhat (@malop nchar(10))
returns table
AS
return (SELECT HV.MaHocVien, DS.MaHocVien FROM f_DanhSachHV() as DS, HOCVIEN as HV
WHERE  Ds.DTB  = dbo.f_TinhDiemTrungBinhCaoNhatCuaMotLop(@malop)
AND DS.MaHocVien = HV.MaHocVien
AND HV.MaLop = @malop
)
GO
select dbo.f_DanhSachHocVienDiemCaoNhat(N'LH000002') AS N'Điểm trung bình cao nhất'




--Danh sách các sinh viên khoa “Công nghệ Thông tin” khoá 2002-2006.

SELECT * FROM SinhVien as SV, Lop, Khoa, KhoaHoc
Where SV.maLop = Lop.maLop and Lop.maKhoa = Khoa.maKhoa and Khoa.maKhoa = N'CNTT'
and KhoaHoc.maKhoaHoc = Lop.maKhoaHoc and Lop.maKhoaHoc = N'K2002'

-- Cho biết các sinh viên (MSSV, họ tên ,năm sinh) của các sinh viên học sớm hơn tuổi qui định (theo tuổi qui định thi sinh viên đủ 18 tuổi khi bắt đầu khóa học).

SELECT SV.maSinhVien, SV.hoTen, SV.namSinh, KH.namBatDau - SV.namSinh as N'Số tuổi' FROM SinhVien as SV, KhoaHoc as KH, Lop
WHERE SV.maLop = Lop.maLop and Lop.maKhoaHoc = KH.maKhoahoc and KH.namBatDau - SV.namSinh < 18


-- Cho biết sinh viên khoa CNTT, khoá 2002-2006 chưa học môn cấu trúc dữ liệu

SELECT * FROM SinhVien as SV, Lop, Khoa, KhoaHoc
Where SV.maLop = Lop.maLop and Lop.maKhoa = Khoa.maKhoa and Khoa.maKhoa = N'CNTT'
and KhoaHoc.maKhoaHoc = Lop.maKhoaHoc and Lop.maKhoaHoc = N'K2002'
and SV.maSinhVien not in
(SELECT KetQua.maSinhVien FROM KetQua,GiangKhoa, SinhVien as SV
Where KetQua.maGiangKhoa = GiangKhoa.maGiangKhoa and SV.maSinhVien = KetQua.maSinhVien
And GiangKhoa.maMonHoc = N'THCS01')

-- Cho biết sinh viên thi không đậu (diem <5) môn cấu trúc dữ liệu 1 nhưng chưa thi lại.
SELECT SV.maSinhVien as N'MSSV', SV.hoTen as N'Họ tên' FROM SinhVien as SV, KetQua as KQ, GiangKhoa as GK,MonHoc as MH
WHERE SV.maSinhVien = KQ.maSinhVien and KQ.maGiangKhoa = GK.maGiangKhoa and  MH.maMonHoc = GK.maMonHoc and MH.tenMonHoc = N'Cấu trúc dữ liệu 1' and KQ.diem < 5 and KQ.lanThi < 2

-- Với mỗi lớp thuộc khoa CNTT, cho biết mã lớp, mã khóa học, tên chương trình và số sinh viên thuộc lớp đó.

SELECT Lop.maLop, Lop.maKhoaHoc, CT.tenChuongTrinh, Lop.maKhoa, Count( SV.maSinhVien) as N'Số sinh viên' FROM Lop, SinhVien as SV, ChuongTrinh as CT
WHERE CT.maChuongTrinh = Lop.maChuongTrinh and SV.maLop = Lop.maLop  and Lop.maKhoa = N'CNTT' Group by Lop.maLop,Lop.maKhoaHoc,CT.tenChuongTrinh,Lop.maKhoa

--  Cho biết điểm trung bình của sinh viên có mã số 0212003 (điểm trung bình chỉ tính trên lần thi sau cùng của sinh viên)


select AVG (D.diem) as N'Diem Trung Binh SV 0212003'  from (

-- Chay ok roi, y tuong la: chi  lay nhung dong ma no thi lan 2, hoac neu lan 1 ma khong thi lan 2, hieu ko?
SELECT KQ.maSinhVien , KQ.diem, KQ.lanThi,KQ.maGiangKhoa ,  Gk.maMonHoc  FROM GiangKhoa as GK,KetQua as KQ
WHERE
KQ.maSinhVien = '0212003' and KQ.maGiangKhoa = GK.maGiangKhoa
AND
(
lanthi = 2 -- Chi lay nhung lan thi thu 2
OR
(lanthi = 1 and Gk.maMonHoc not in (SELECT Gk.maMonHoc  FROM GiangKhoa as GK,KetQua as KQ WHERE KQ.maSinhVien = '0212003' and KQ.maGiangKhoa = GK.maGiangKhoa and lanthi = 2)) -- Va lay nhung lan thi 1 neu khong thi lan 2
)
) as D





Use QuanLyHocVien
--Xuất ra danh sách họ tên các giáo viên, ứng với mỗi giáo viên cho biết có số môn mà
--các giáo viên này đã được phân công giảng dạy.

DECLARE @tenGV nvarchar(50);
DECLARE @soMonDay int;
DECLARE curDanhSachGiaoVienDaDayMon CURSOR
FORWARD_ONLY
FOR SELECT GV.TenGV, COUNT(MH.MaMonHoc) AS 'SỐ MON ĐÃ DẠY' FROM GIAOVIEN AS GV, GIAOVIEN_DAY_MONHOC AS GVMH, MONHOC AS MH
WHERE GV.MaGV = GVMH.MaGV AND GVMH.MaMH = MH.MaMonHoc
GROUP BY  GV.TenGV
open curDanhSachGiaoVienDaDayMon
FETCH NEXT FROM curDanhSachGiaoVienDaDayMon INTO @tenGV, @soMonDay
print N'STT   ' + N'    Tên giáo viên                      ' + N'Số môn đã dạy'
print ''
DECLARE @STT7 int = 1
WHILE @@FETCH_STATUS = 0
BEGIN
print cast(@STT7 as nchar(5))+ '     ' + cast(@tenGV as nchar(30)) + '             '+ cast(@soMonDay as nvarchar(50))
FETCH NEXT FROM curDanhSachGiaoVienDaDayMon INTO @tenGV, @soMonDay
SET @STT7 += 1
END
Close curDanhSachGiaoVienDaDayMon
DealLocate curDanhSachGiaoVienDaDayMon
--2. Nhập vào một mã giáo viên, xuất ra tên giáo viên, danh sách tên các môn giáo viên
--giảng dạy cùng số lần dạy theo định dạng của ví dụ sau:
-- **Tên giáo viên : Trịnh Hoài An
-- **Danh sách các môn được phân công giảng dạy
-- ******1. Cấu trúc dữ liệu : 3 lần
-- ******2. Cơ sở dữ liệu : 5 lần


--Khai báo biến cursor, biếh cục bộ
ALtER PROC ThongTinGiaoVien
@maGiaoVien nchar(10)
as
BEGIN
DECLARE @tenGiaoVien nvarchar(50);
DECLARE @tenMonHoc nvarchar(50);
DECLARE @soLanDay int;
DECLARE cur_GiaoVien CURSOR
FORWARD_ONLY
FOR
SELECT GV.TenGV, MH.TenMonHoc, GV_DAY_MH.ThamNien FROM GIAOVIEN AS GV, GIAOVIEN_DAY_MONHOC AS GV_DAY_MH, MONHOC AS MH
WHERE GV.MaGV = GV_DAY_MH.MaGV AND GV_DAY_MH.MaMH = MH.MaMonHoc AND GV.MaGV LIKE @maGiaoVien
-- Mở cursor
open cur_GiaoVien
-- 3 Đọc và nhập dữ liệu
FETCH NEXT FROM cur_GiaoVien into  @TenGiaoVien, @tenMonHoc, @soLanDay
print ('** Tên Giáo Viên: ' + @TenGiaoVien)
print (N'** Danh sách các môn được phân công giảng dạy')
DECLARE @STT5 int = 1
WHILE @@FETCH_STATUS = 0
BEGIN
print N'****** ' + cast(@STT5 as nvarchar(50))+ ' '+ @tenMonHoc  +  ' : ' + cast(@soLanDay as nvarchar(50))  + N' lần'
FETCH NEXT FROM cur_GiaoVien   INTO @TenGiaoVien, @tenMonHoc, @soLanDay
SET @STT5 += 1
END
Close cur_GiaoVien
Deallocate cur_GiaoVien
END
DECLARE @kq INT
EXEC @kq = ThongTinGiaoVien  'GV00005   '




--3. Nhập vào một mã môn, xuất ra thông tin môn (tên môn, số tín chỉ) cùng danh sách các
--học viên đã từng thi đậu môn này theo định dạng của ví dụ sau (lưu ý: nếu học viên thi
--đậu hai lần cũng chỉ xuất 1 lần):
--**Môn : Cấu trúc dữ liệu
--**Số tín chỉ : 4 tín chỉ
--**Danh sách học viên thi đậu
--******1. Lê Thanh Tùng
--******2. Trịnh Ngọc Thanh
CREATE PROC HOCVIENTHIDAUTHEOMON
@maMH nchar(10)
as
BEGIN
DECLARE @maMon nchar(10);
DECLARE @tenMon nvarchar(50);
DECLARE @soTinChi int;
DECLARE @tenHocVien nvarchar(50);

DECLARE curListHocVienThiDau CURSOR
FORWARD_ONLY
FOR
SELECT MH.TenMonHoc, MH.SoChi, HV.TenHocVien FROM MONHOC AS MH, HOCVIEN AS HV, KETQUA AS KQ
WHERE HV.MaHocVien = KQ.MaHV AND KQ.MaMonHoc = MH.MaMonHoc AND KQ.Diem >=5  AND MH.MaMonHoc LIKE @maMH

open curListHocVienThiDau

FETCH NEXT FROM curListHocVienThiDau INTO @tenMon, @soTinChi,@tenHocVien
print N'** Môn: ' + @tenMon
print N'** Số tín chỉ: ' + cast(@soTinChi as nvarchar(50))
print N'** Danh sách học viên thi đậu'
DECLARE @STT4 int = 1
WHILE @@FETCH_STATUS = 0
BEGIN
print '****** ' + cast(@STT4 as nvarchar(50)) + ' ' +  + @tenHocVien
FETCH NEXT FROM curListHocVienThiDau INTO @tenMon, @soTinChi,@tenHocVien
SET @STT4 += 1
END

Close curListHocVienThiDau
Deallocate curListHocVienThiDau
END
GO

DECLARE @kq INT
EXEC @kq = HOCVIENTHIDAUTHEOMON  'MH00001   '


--4. Nhập vào mã lớp, xuất ra thông tin lớp (mã lớp, tên lớp trưởng) cùng danh sách các học
--viên của lớp (họ tên học viên và điểm trung bình) theo định dạng của ví dụ sau:
--**Lớp : LH000001
--**Lớp trưởng : Lê Thanh Tùng
--**Danh sách học viên
--******1. Lê Thanh Tùng : 7.52
--******2. Trịnh Ngọc Thanh : 2.15

CREATE proc THONGTINLOPHOC
 @maLop nchar(10)
as
BEGIN

DECLARE @tenLopTruong nvarchar(50);
DECLARE @tenHV nvarchar(50);
DECLARE @diemTrungBinh float;

DECLARE curThongTinLopHoc CURSOR
FORWARD_ONlY
FOR
SELECT HV.MaLop, HV3.TenHocVien as N' Tên lớp trưởng', hv.TenHocVien, BangDiemTB.DTB FROm
(SELECT  hv.MaHocVien,ROUND( SUM(KQ.Diem * MH.SoChi)/SUM(MH.SoChi), 2) as DTB
FROM  KETQUA AS KQ, MONHOC AS MH, HOCVIEN AS HV, LOPHOC AS LH
WHERE LH.MaLop = HV.MaLop AND  KQ.MaMonHoc = MH.MaMonHoc AND HV.MaHocVien = KQ.MaHV AND LH.MaLop = @maLop
AND LANTHI =
(SELECT MAX(LANTHI)
FROM KETQUA as kq2, MONHOC as mh2, HOCVIEN as hv2
WHERE kq2.MaMonHoc = mh2.MaMonHoc and hv2.MaHocVien = kq2.MaHV AND hv2.MaHocVien =  HV.MaHocVien)
GROUP BY hv.MaHocVien
) as BangDiemTB, -- Để lấy mã học viên và điểm TB
HOCVIEN as HV -- Để lấy chi tiết học viên trên
,LOPHOC as LH, -- Để lấy mã lớp trưởng
HOCVIEN as HV3 -- Để lấy tên thông tin lớp trưởng
WHERE BangDiemTB.MaHocVien = hv.MaHocVien
 AND LH.MaLop = HV.MaLop
 AND HV3.MaHocVien = LH.LopTruong



open curThongTinLopHoc
FETCH NEXT FROM curThongTinLopHoc INTO @maLop, @tenLopTruong, @tenHV, @diemTrungBinh
print N'** Lớp: ' + @maLop
print N'** Lớp trưởng: ' + @tenLopTruong
print N'**Danh sách học viên'
DECLARE @STT int = 1

WHILE @@FETCH_STATUS = 0
BEGIN
print '******' + cast(@STT as nvarchar(50)) +  '. ' +  @tenHV + ' : ' + cast(@diemTrungBinh as nvarchar(50))
FETCH NEXT FROM curThongTinLopHoc INTO @maLop, @tenLopTruong, @tenHV, @diemTrungBinh
SET @STT += 1
END
Close curThongTinLopHoc
Deallocate curThongTinLopHoc

END
GO

DECLARE @kq INT
EXEC @kq = THONGTINLOPHOC  'LH000001  '



--5. Nhập vào mã học viên xuất ra bảng điểm theo định dạng của ví dụ sau (điểm số tính trên
--lần thi sau cùng của học viên):
CREATE PROC XUATBANGDIEM
@maHocVien nchar(10)
as
BEGIN
DECLARE @hoTen nvarchar(50);
DECLARE @tenLop nvarchar(50);
DECLARE @monHoc nvarchar(50);
DECLARE @soTC int;
DECLARE @Diem float;
DECLARE curBangDiemHV CURSOR
FORWARD_ONlY
FOR
SELECT hv.TenHocVien, hv.MaLop, mh.TenMonHoc, mh.SoChi, kq.Diem FROM HOCVIEN AS HV, KETQUA AS KQ, MONHOC AS MH
WHERE HV.MaHocVien = KQ.MaHV AND KQ.MaMonHoc = MH.MaMonHoc AND HV.MaHocVien LIKE @maHocVien
AND  LANTHI =
(SELECT MAX(LANTHI)
FROM KETQUA as kq2, MONHOC as mh2, HOCVIEN as hv2
WHERE kq2.MaMonHoc = mh2.MaMonHoc and hv2.MaHocVien = kq2.MaHV AND hv2.MaHocVien =  HV.MaHocVien)
open curBangDiemHV
FETCH NEXT FROM curBangDiemHV INTO @hoTen,@tenLop,@monHoc,@soTC,@Diem
print N'**Họ tên: ' + @hoTen
print N'**Lớp: ' + @tenLop
print N'**Kết quả học tập'
print 'STT            ' + N'Môn học           '+ N'Số tín chỉ         ' + N'Điểm'
DECLARE @STT2 int = 1
WHILE @@FETCH_STATUS = 0
BEGIN
print ' '+cast(@STT2 as nvarchar(50)) + '           ' + @monHoc + '           ' + CAST(@soTC AS NVARCHAR(50)) + '                ' + CAST(@Diem AS NVARCHAR(50))
FETCH NEXT FROM curBangDiemHV INTO @hoTen,@tenLop,@monHoc,@soTC,@Diem
SET @STT2 += 1
END
Close curBangDiemHV
Deallocate curBangDiemHV
END
GO
DECLARE @kq int
EXEC XUATBANGDIEM N'HV000002  '
--1. Cho danh sách các giáo viên đã đến tuổi về hưu (>60 đối với nam, >55 đối với nữ)
CREATE PROC DanhSachGiaoVienDaVeHuu
AS
BEGIN
DECLARE @namsinh as int

SELECT GV.MaGV, GV.TenGV, GV.NgaySinh, GV.GioiTinh, ( YEAR(GETDATE()) -  YEAR(GV.NgaySinh)) as N'Tuổi'  FROM GIAOVIEN as GV
WHERE YEAR(GETDATE()) -  YEAR(GV.NgaySinh) >= (CASE gv.GioiTinh WHEN N'Nam' THEN 60 WHEN N'Nữ' THEN 55 END)
END
GO
EXEC DanhSachGiaoVienDaVeHuu

-- 2. Cho danh sách các sinh viên đã thi 3 lần mà vẫn không đậu môn ABC
CREATE PROC HocVienThiBaLanChuaDau
@tenMonHoc nvarchar(50)
AS
BEGIN
SELECT * FROM HOCVIEN as HV, KETQUA as KQ , MONHOC AS MH
WHERE KQ.MaMonHoc = MH.MaMonHoc and HV.MaHocVien = KQ.MaHV and KQ.LanThi >=3 AND KQ.Diem < 5 AND MH.TenMonHoc LIKE @tenMonHoc
END
GO
DECLARE @kq nvarchar(100)
EXEC HocVienThiBaLanChuaDau N'Khai thác dữ liệu'

--3. Cho danh sách các giáo viên được phân công giảng dạy những môn ngoài chuyên môn của gv đó

ALTER PROC GIAOVIENDUOCPHANCONGDAYNGOAIMON

AS
BEGIN
SELECT GV2.TenGV FROM GIAOVIEN as GV2, PHANCONG as PC2
WHERE GV2.MaGV = PC2.MaGV -- Phân công
AND PC2.MaMH NOT IN
(
SELECT GVDMH.MaMH FROM GIAOVIEN as GV, GIAOVIEN_DAY_MONHOC as GVDMH
WHERE GV.MaGV = GVDMH.MaGV AND GV.MaGV = GV2.MaGV -- Chuyên môn
)
GROUP BY GV2.TenGV
END
GO

EXEC GIAOVIENDUOCPHANCONGDAYNGOAIMON


--4.Mỗi giáo viên chỉ chủ nhiệm 1 lớp trong 1 năm học. Hãy cho danh sách các giáo viên được phân công chủ nhiệm sai yêu cầu trên.
CREATE PROC GIAOVIENPHANCONGSAIYEUCAU
AS
BEGIN
SELECT distinct gv.MaGV ,gv.TenGV
FROM GIAOVIEN gv,LOPHOC lh
WHERE gv.MaGV = lh.GVQuanLi
and (lh.NamKetThuc - lh.NamBatDau ) >1
or exists (select lh.GVQuanLi from LOPHOC lh1 where lh1.GVQuanLi = lh.GVQuanLi and lh1.MaLop != lh.MaLop   )
END
GO
EXEC GIAOVIENPHANCONGSAIYEUCAU

--5. Cho biết năm nay có bao nhiêu học sinh giỏi, bao nhiêu học sinh khá, trung bình
ALTER PROC SOHOCVIENTHEOHOCLUC
AS
BEGIN
SELECT  count(hv1.TenHocVien)  as N'Số học sinh Trung bình'
FROM HOCVIEN hv1
WHERE hv1.MaHocVien  in (SELECT  kq.MaHV    FROM KETQUA kq,MONHOC mh,HOCVIEN hv
WHERE kq.MaMonHoc = mh.MaMonHoc and kq.MaHV = hv.MaHocVien
and kq.LanThi >= ALL(SELECT kq1.LanThi  FROM KETQUA kq1
WHERE  kq1.MaMonHoc = mh.MaMonHoc and kq1.MaHV = kq.MaHV )
group by kq.MaHV
having (SUM(mh.SoChi *kq.Diem )/SUM(mh.SoChi )) >= 5
and (SUM(mh.SoChi *kq.Diem )/SUM(mh.SoChi )) < 6.5 )


SELECT count(hv2 .MaHocVien ) as N'Số học sinh Khá'
FROM HOCVIEN hv2
WHERE exists (SELECT count( hv.TenHocVien)   FROM KETQUA kq,MONHOC mh,HOCVIEN hv
WHERE kq.MaMonHoc = mh.MaMonHoc and kq.MaHV = hv.MaHocVien and hv2.MaHocVien = hv.MaHocVien
and kq.LanThi >= ALL(SELECT kq1.LanThi  FROM KETQUA kq1 ,MONHOC mh1
WHERE kq1.MaMonHoc =mh1 .MaMonHoc and kq1.MaHV = kq.MaHV )
group by kq.MaHV ,hv.TenHocVien
having (SUM(mh.SoChi *kq.Diem )/SUM(mh.SoChi )) >= 6.5
and (SUM(mh.SoChi *kq.Diem )/SUM(mh.SoChi )) < 8 )

SELECT count(hv3.MaHocVien ) as  N'Số học sinh giỏi '
FROM HOCVIEN hv3
WHERE exists (SELECT count( hv.TenHocVien)   FROM KETQUA kq,MONHOC mh,HOCVIEN hv
WHERE kq.MaMonHoc = mh.MaMonHoc and kq.MaHV = hv.MaHocVien and hv3.MaHocVien = hv.MaHocVien
and kq.LanThi >= ALL(SELECT kq1.LanThi  FROM KETQUA kq1 ,MONHOC mh1
WHERE kq1.MaMonHoc =mh1 .MaMonHoc and kq1.MaHV = kq.MaHV )
group by kq.MaHV ,hv.TenHocVien
having (SUM(mh.SoChi *kq.Diem )/SUM(mh.SoChi )) >= 8
and (SUM(mh.SoChi *kq.Diem )/SUM(mh.SoChi )) < 9 )
END
GO
EXEC SOHOCVIENTHEOHOCLUC

USE SinhVien

--------------------------------------------BAI TAP LY THUYET
-- TAO KHUNG NHIN TREN VIEW
CREATE VIEW VIEW_SVLH
AS
SELECT MASV, HOTEN, DIACHI, LH.MALOP, TENLOP, SISO
FROM SinhVien, LopHoc LH
WHERE SinhVien.LopHoc = LH.MaLop

SELECT * FROM VIEW_SVLH

-- VIET TRIGGER INSTEAD OF DE CHO PHEP INSERT TREN VIEW
CREATE TRIGGER TRIGGER_VIEW_SVLH ON VIEW_SVLH INSTEAD OF INSERT
AS BEGIN
IF(NOT EXISTS(SELECT LH.MALOP FROM INSERTED, LOPHOC LH WHERE LH.MALOP = INSERTED.MALOP))
BEGIN
INSERT INTO LOPHOC SELECT MALOP, TENLOP, SISO FROM INSERTED
END
IF (NOT EXISTS(SELECT SV.MASV FROM SINHVIEN SV, INSERTED I WHERE SV.MASV = I.MASV))
BEGIN
INSERT INTO SINHVIEN SELECT MASV, HOTEN, MALOP, DIACHI FROM INSERTED
END
ELSE
BEGIN
UPDATE SINHVIEN SET HOTEN = I.HOTEN, LOPHOC = I.MALOP, DIACHI = I.DIACHI FROM INSERTED I, SINHVIEN SV
WHERE SV.MASV = I.MASV
END
END

----------------------------------------------BAI TAP 1
--1. TAO VIEW XUAT THONG TIN MA SINH VIEN, TEN SINH VIEN VA DIEM TRONG LAN THI SAU CUNG CUA SINH VIEN
create view View_Cau1
as
select SV.MASV, HOTEN, DIEM
from SINHVIEN SV, KETQUA KQ
WHERE SV.MASV= KQ.MASV AND KQ.LANTHI IN (SELECT MAX(KQ1.LANTHI)
FROM KETQUA KQ1
WHERE KQ1.MASV = KQ.MASV AND KQ1.MAMH = KQ.MAMH)

SELECT * FROM View_Cau1

-- 2 CAP NHAT DIEM THI LAN SAU CUNG CUA SINH VIEN

create TRIGGER UPDATE_VIEW_CAU1 ON View_Cau1 INSTEAD OF UPDATE
AS BEGIN
UPDATE View_Cau1 SET DIEM = I.DIEM FROM INSERTED I INNER JOIN View_Cau1 I2 ON I.MASV= I2.MASV WHERE I2.MASV= I.MASV and MAMH = KetQua.MaMH
END

UPDATE View_Cau1 SET DIEM = 8 WHERE MASV = N'1262078'
DROP TRIGGER UPDATE_VIEW_CAU1

--- 3 XÓA 1 SINH VIÊN TRÊN VIEW SẼ THÌ SẼ XÓA SINH VIÊN TRONG BẢNG SINH VIÊN

create TRIGGER DELETE_SVVIEW_CAU1 ON View_Cau1 INSTEAD OF DELETE
AS BEGIN
DECLARE @CUR CURSOR
SET @CUR = CURSOR
FOR (SELECT MASV FROM DELETED)
DECLARE @MASV NCHAR(10)
OPEN @CUR
FETCH NEXT FROM @CUR INTO @MASV
WHILE (@@FETCH_STATUS = 0)
BEGIN
DELETE FROM KETQUA WHERE MASV = @MASV
DELETE FROM SINHVIEN WHERE MASV = @MASV
FETCH NEXT FROM @CUR INTO @MASV
END
CLOSE @CUR
DEALLOCATE @CUR
END

DELETE FROM View_Cau1 where MASV  = N'1262078'
SELECT * FROM KETQUA
SELECT * FROM SINHVIEN
DROP TRIGGER DELETE_SVVIEW_CAU1

---------------------- BAI TAP 2
--1. TAO VIEW LAY THONG TIN SINH VIEN, TUOI , MA LOP, SO MON DA HOC CUA SINH VIEN

ALTER VIEW VIEW_CAU2
AS
SELECT  SV.MaSV,SV.HoTen,SV.DiemTB, SV.MaLop,SV.NamSinh,SV.NamBD,SV.NamKT, SV.TinhTrang, COUNT(distinct(MaMH)) SOMONDAHOC, Year(getdate())-NamSinh as Tuoi
FROM SINHVIEN SV,KETQUA KQ
WHERE SV.MaSV = KQ.MaSV
GROUP BY  SV.MaSV,SV.HoTen,SV.DiemTB, SV.MaLop,SV.NamSinh,SV.NamBD,SV.NamKT, SV.TinhTrang

--2. VIET TRIGGER CHI CHO PHEP CAP NHAT TUOI VA THONG TIN CA NHAN CUA SINH VIEN, MA LOP
-- INSERT |UPDATE |DELETE
--SINHVIEN - +(Tuoi,MaLop,HoTen,MaSV) +
--KETQUA +(MAMH) +(MAMH) -
--CACH 1
drop trigger CAPNHAT_VIEW_CAU2
CREATE TRIGGER CAPNHAT_VIEW_CAU22 ON VIEW_CAU2 INSTEAD OF UPDATE
AS BEGIN
IF(UPDATE(HoTen) or update(NamSinh) or update(MaLop))
begin
DECLARE @CUR CURSOR
SET @CUR = CURSOR
FOR (SELECT I.MaSV FROM INSERTED I)
OPEN @CUR
DECLARE @MASV NCHAR(10)
FETCH NEXT FROM @CUR INTO @MASV
WHILE(@@FETCH_STATUS = 0)
BEGIN
IF EXISTS(SELECT * FROM VIEW_CAU2 V WHERE V.MaSV = @MaSV)
begin
UPDATE VIEW_CAU2 SET HoTen = I.HoTen, MaLop = I.MaLop, NamSinh = I.NamSinh
WHERE MaSV = @MASV
end
FETCH NEXT FROM @CUR INTO @MASV
END
CLOSE @CUR
DEALLOCATE @CUR
end
END
drop trigger CAPNHAT_VIEW_CAU2
--cach 2

alter TRIGGER CAPNHAT_VIEW_CAU22 On VIEW_CAU2
Instead of UPDATE
As
Begin
If not exists(select * from inserted I Where MaSV =I.MaSV)
Begin
Raiserror('Không tồn tại sinh viên cần cập nhật',16,1)
Rollback transaction
return
End
UPDATE VIEW_CAU2
  SET HoTen= I2.HoTen,DiemTB = I2.DiemTB ,MaLop = I2.MaLop, NamSinh = I2.NamSinh, NamBD = I2.NamBD, NamKT = I2.NamKT, TinhTrang = I2.TinhTrang
from inserted I2 INNER JOIN VIEW_CAU2 HV2 ON I2.MaSV = HV2.MaSV
  WHERE HV2.MaSV = I2.MaSV

End
-- KIEM TRA UPDATE
select * from VIEW_CAU2
UPDATE VIEW_CAU2 SET HoTen = N'Phạm Hiền', DiemTB = 10 ,MaLop = '12CK2', NamSinh = '1994',NamBD = 2012, NamKT = 2015, TinhTrang = 'Đang học', SOMONDAHOC = 3, Tuoi = 21
where MaSV = '1262076'
---- lỗi Msg 4403, Level 16, State 1, Procedure CAPNHAT_VIEW_CAU22, Line 11
--Cannot update the view or function 'VIEW_CAU2' because it contains aggregates, or a DISTINCT or GROUP BY clause, or PIVOT or UNPIVOT operator.

--3. viet trigger cho phep them 1 sinh vien vao csdl
alter trigger Insert_View_Cau2 on VIEW_CAU2 INSTEAD OF INSERT
AS BEGIN
if not exists(select * from SinhVien SV, Inserted I where I.MaSV= SV.MaSV)
begin
INSERT INTO SinhVien
SELECT MaSV, HoTen,DiemTB,MaLop,NamSinh,NamBD,NamKT,TinhTrang
FROM INSERTED;
end
update SinhVien set HoTen = I.HoTen, DiemTB = I.DiemTB, MaLop = I.MaLop, NamBD = I.NamBD, NamKT = I.NamKT, TinhTrang = I.TinhTrang
From SinhVien sv, Inserted I where sv.MaSV =I.MaSV
END

-- KIEM TRA INSERT
insert into VIEW_CAU2 values ('1262079',N'Hiền Phạm',10,'12CK1',1994,2012,2014,'Đang học')
-- loi Column name or number of supplied values does not match table definition.

------------------------------BAI TAP 3
-- 1. tao view cho biet thong Tin cua 3 sinh vien co diem tb cap nhat cua moi lop. Xep giam theo diem TB
ALTER view VIEW_CAU3
AS
SELECT TOP 3*
FROM SINHVIEN
ORDER BY DIEMTB DESC

SELECT * FROM VIEW_CAU3
--2. viet trigger cho phep tang 0.5 diem Tb cao nhat neu DTB > 9.0

ALTER TRIGGER UPDATE_VIEW_CAU3  ON VIEW_CAU3 INSTEAD OF UPDATE
AS BEGIN
IF EXISTS(SELECT * FROM INSERTED WHERE DIEMTB > 9.0)
BEGIN
UPDATE VIEW_CAU3 SET DIEMTB = DIEMTB+0.5
END
END

--3. VIET TRIGGER CHO PHEP THEM 1 SINH VIEN VAO CSDL (DIEM TB DUOC TINH)

CREATE TRIGGER INSERT_VIEW_CAU3 ON VIEW_CAU3 INSTEAD OF INSERT
AS BEGIN
declare @cur cursor
set @cur = CurSor for (select MaSV from Inserted)
open @cur
declare @MaSV nchar(10)
fetch next from @cur into @MaSV
while(@@fetch_status = 0)
begin
IF NOT EXISTS(SELECT * FROM INSERTED I, SINHVIEN SV where SV.MaSV= I.MaSV)
begin
declare @TinhDiem float
select @TinhDiem = (Sum(KQ.Diem*MH.SoChi)/Sum(MH.SoChi))
from SinhVien SV, MonHoc MH, KetQua KQ
where SV.MaSV = KQ.MaSV and KQ.MaMH = MH.MaMH and KQ.LanThi in (select max(KQ1.LanThi)
from KetQua KQ1
where KQ1.MAMH = KQ.MAMH
AND KQ1.MASV = KQ.MASV)
insert into VIEW_CAU3 select MaSV,HoTen,DiemTB = @TinhDiem, MaLop,NamSinh,NamBD,NamKT, TinhTrang from Inserted;
end
fetch next from @cur into @MaSV
end
close @cur
deallocate @cur
END

---------------------------bai tap 4

Sunday, December 14, 2014

KIẾM TIỀN TRIỆU MỖI THÁNG TỪ 8SHARECỰC KỲ DỄ 500đ/CLICK

2:45 AM By

Chào các bạn!

Tình cờ mình kiếm được một cách kiếm tiền đơn giản mà bạn có thể kiếm tiền triệu mỗi ngày với việc chia sẻ tin từ 8share.vn giá cực kì hấp dẫn 500đ/1 click đơn giản mà có tiền . chỉ cần dành ra 3 phút mỗi ngày là bạn sẽ có cơ hội kiếm rất rất nhiều tiền rồi. Nhanh tai đăng ký nhé

Hướng Dẫn Chi Tiết:

Bước 1: Click vào đây để đăng ký hoặc đăng ký tại link sau:http://bit.ly/1wuaTdf

Bước 2: Click vào Đăng Ký Ngay hình trên sau đó điền đầy đủ thông tin như, Tên tài khoản, email, số điện thoại, mật khẩu ....

Bước 3: Vào Email đã đăng ký để kích hoạt tài khoản sau đó tiền hành đăng nhập và bắt đầu chia sẻ thông tin trên 8share.vn rồi ngồi chơi chờ tiền về.

Hướng Dẫn Kiếm Tiền với 8share.vn

Bước 1: Đăng Nhập Vào Tài Khoản.
Bước 2: click vào tin đặc biệt và chọn tin hot mà bạn muốn chia sẻ sau đó chia sẻ lên các mạng xã hội hoặc coppy link chia sẻ qua yahoo, group,.... Mỗi click là bạn được 500đ mỗi ngày cũng kiếm được kha khá đấy.


Tiếp theo bạn kéo xuống dưới:
chia-se-kiem-tien-tu-8share
cách chơi kiếm tiền 8share.vn
  • Chọn thông điệp chia sẻ của bạn hay chính là tiêu đề bài post của bạn.
  • Lấy link chia sẻ. Bạn có thể chia sẻ lên mạng xã hội Facebook, G+, Twitter, hay các diễn đàn,…
4. Tiền được tính như thế nào?
– Với mỗi lượt truy cập hợp lệ bạn được trả 500 VNĐ. Tất cả các các truy cập được tính đều phải ở Việt Nam.
thanh-toan-kiem-tien-8share
– Max tối đa là 50 click/ tin. Click được tính tiền là click đầu tiên và duy nhất của một IP
8share.vn-kiem-tien-tren-mang
8share.vn đủ 500k là kiếm tiền trên mạng dễ dàng
Chú ý:
Tối đa chỉ 50view/tin, view được tính tiền là view đầu tiên và duy nhất của 1 IP. Vậy việc lập hội view chéo cho nhau sẽ không hiệu quả (khi bạn đã xem 1 tin nào đó thì bạn xem lại tin đó của bất kỳ ai đều không được tính nữa).

Mời bạn bè để kiếm thêm 10.000 đồng/1 tài khoản từ 8share.vn

8share.vn cung cấp cho bạn hình thức Mời bạn bè để nhận 10.000 VNĐ vào tài khoản. Vậy cách thứ thực hiện ra sao ?.
Tại thanh bên trái, bạn click vào Mời bạn bè.
cach-kiem-tien-tu-8share-vn
mời bạn bè chơi 8share nhận ngay tiền
Lưu ý: Bạn phải cập nhật đầy đủ thông tin ngân hàng vì 8share sẽ trả tiền cho bạn bằng vnđ thanh toán qua ngân hàng nhé.

Các bạn click vào đây:http://bit.ly/1wuaTdf đăng ký! 

Wednesday, November 19, 2014

NASA BÁO ĐỘNG: QUẢ ĐẤT SẼ CHÌM TRONG BÓNG TỐI 6 NGÀY ĐÊM TỪ 16 ĐẾN 22-12-2014!

8:31 PM By

TIN RẤT QUAN TRỌNG DO CƠ QUAN NASA HOA KỲ THÔNG BÁO CHO TOÀN ĐỊA CẦU:
QUẢ ĐẤT SẼ HOÀN TOÀN CHÌM TRONG BÓNG TỐI SUÔT 6 NGÀY ĐÊM TỪ 16-12-2014 ĐẾn 22-12-2014 VÌ BỊ BÃO MẶT TRỜI!

Ảnh minh họa
Xin hãy xem Video theo Link kèm dưới đây để theo dõi Thông Báo Khẩn Cấp của Giám Đốc Charles Bolden của Cơ quan Hàng Không Vũ Trụ NASA Hoa Kỳ (National Aeronautics and Space Administration) vừa thông báo cuối tuần rồi rằng toàn bộ Trái Đất sẽ hoàn toàn chìm vào bóng tối trong 6 ngày đêm kể từ ngày 16 tháng 12 đến ngày 22 tháng 12 năm 2014 vì lý do Bão Mặt Trời lớn nhất trong 250 năm trở lại đây!



Ông Giám Đốc NASA khuyến khích mọi người nên bình tĩnh và chuẩn bị mọi thứ cần thiết cho 6 ngày đêm tối tăm kia và đề phòng mọi bất trắc gì khác có thể tấn công vào các cộng đồng dân chúng.  

Giám Đốc NASA Charles Bolden giải thích rằng cơn Bão Mặt Trời sẽ cuốn cát bụi và những mãnh vụn rác rưỡi không gian làm che khuất tới 90% Mặt Trời nên sẽ tối tăm toàn nhân loại!

NASA cảnh báo dân chúng Hoa Kỳ cần chuẩn bị chu đáo và thật bình tĩnh đề phòng mọi bất trắc xảy ra. Các bộ năng lượng, Điện Lực Hoa Kỳ được chỉ thị sẵn sàng cung cấp ánh sáng đầy đủ và liên tục. Các Bộ Quốc Phòng, Nội An đều sẵn sàng ứng phó và đề phòng các hoạt động khủng bố; trộm cướp.

Riêng dân chúng được khuyến khích chuẩn bị hộp quẹt, đèn, pin, đèn bấm, thực phẩm, gạo và nước đầy đủ cho 6 ngày đêm chìm trong bóng tối. Mỗi gia đình cũng nên có một Radio để nghe thông báo khẩn. Xin quý vị và các bạn xem ngay Video của NASA và chuyển tin nầy cho mọi người được biết!


Đây chỉ là tin tức do một số báo chí và các Diễn Đàn Internet công bố. Chúng tôi chỉ làm nhiệm vụ lượm lặt và thông tin chứ không biết sự kiện sẽ ra sao. Không thấy NASA cải chính vì có tin nói rằng tin nầy là “xạo”. Dù sao để biết và đề phòng vẫn hơn.. Thế giới ngày nay xảy ra các thiên tai, sóng thần, động đất, dịch bệnh và khủng bố thảm sát là chuyện có thật và không ai biết sẽ xảy đến cho mình và gia đình mình vào lúc nào. Xin cầu nguyện, cầu chúc mọi người được bình an, sức khỏe, hạnh phúc và nhiều thăng hoa trong cuộc sống.
Nguồn: http://dailybuzzlive.com/alert-nasa-confirms-earth-will-go-dark-6-days-december-2014/#sthash.WULDfuU7.dpuf

BẠN SẴN SÀNG CHƯA?

Định nghĩa của tôi về “cơ hội” là “sự sẵn sàng” vì CHỈ khi bạn sẵn sàng thì cơ hội mới tới. Dễ nhìn vào thành công của ai đó và nghĩ rằng bạn có thể làm được điều đó nữa. NHƯNG điều đó là sai vì ai đó đã sẵn sàng và nắm lấy cơ hội nhưng bạn thì KHÔNG. Về căn bản, bạn KHÔNG sẵn sàng khi cơ hội tới.
Năm kia Facebook mua một công ti nhỏ có tên là Instagram với giá $1 tỉ đô la. Instagram là một công ti khởi nghiệp nhỏ chỉ với 12 người cho nên mọi người trong họ đều lập tức thành triệu phú. Khi tin này được công bố, nhiều sinh viên nói với tôi: “Em cũng có thể xây dựng được công ti tương tự như công ti đó, ý tưởng là đơn giản, và công nghệ là dễ dàng.” Đây không phải là lần đầu tiên tôi nghe thấy lời bình luận như thế cho nên tôi bảo họ rằng họ nên hiểu từ “Cơ hội.”
Định nghĩa của tôi về “cơ hội” là “sự sẵn sàng” vì CHỈ khi bạn sẵn sàng thì cơ hội mới tới. Dễ nhìn vào thành công của ai đó và nghĩ rằng bạn có thể làm được điều đó nữa. NHƯNG điều đó là sai vì ai đó đã sẵn sàng và nắm lấy cơ hội nhưng bạn thì KHÔNG. Về căn bản, bạn KHÔNG sẵn sàng khi cơ hội tới.
Ba mươi năm trước, khi Steve Jobs tạo ra máy tính Apple, nhiều người trong các bạn tôi đã mua máy tính này, nhìn vào bên trong và nói rằng nó đơn giản tới mức bất kì ai cũng có thể dựng được nó. Một người nói: “Nó là đơn giản vì Steve Jobs thậm chí đã không hoàn thành đại học, chúng tôi có thể thiết kế máy tính tốt hơn nhiều so với máy đó.” Tôi bảo họ: “Bạn là sinh viên đại học và bạn có thể làm được tốt hơn NHƯNG Steve sẵn sàng khi cơ hội tới còn bạn thì không.” Cùng điều này đã xảy ra với DOS của Microsoft vài năm sau. MSDOS chỉ là một chương trình đơn giản với vài nghìn dòng mã. Ngày nay bất kì sinh viên khoa học máy tính nào cũng có thể viết ra một hệ điều hành như cái đó hay thậm chí hay hơn. NHƯNG Bill Gates đã sẵn sàng khi IBM cần có một hệ điều hành cho PC của nó.
Từ quan điểm kĩ thuật, KHÔNG có khác biệt giữa Instagram, Apple Computer, Microsoft DOS và phiên bản đầu của Google khi những sản phẩm này ra. Chúng tất cả đều đơn giản và dễ làm, từ cảnh quan ngày nay. Lí do chúng xứng với nhiều tiền thế và những công ti này thành công thế vì họ ra trước và nắm lấy cơ hội khi cơ hội tới. Sự kiện là tất cả họ đều chẳng liên quan gì tới công nghệ NHƯNG họ sẵn sàng khi cơ hội đúng tới.
Những người doanh nghiệp gọi nó là “Thế thượng phong đầu tiên” hay là sản phẩm đầu tiên trên thị trường để đáp ứng cho nhu cầu hay giải quyết một vấn đề. Vì họ là người đầu tiên khi không có kẻ cạnh tranh khác và mọi người phải dùng sản phẩm của họ. Khi họ trở nên quen thuộc với điều đó, họ sẽ KHÔNG chuyển sang sản phẩm khác, cho dù sản phẩm mới là tốt hơn. Đây là lí do tại sao Steve Jobs thành công thế vì ông ấy bao giờ cũng muốn là “người đầu tiên trên mọi thứ.” Ông ấy đã tạo ra máy tính cá nhân đầu tiên, máy nghe nhạc MP3 tích hợp đầu tiên, iPod; điện thoại thông minh đầu tiên, iPhone; và máy tính bảng đầu tiên, iPad. Ông ấy nói: “Thiết kế là quan trọng nhưng đúng thời điểm là mọi thứ.” Đúng thời điểm nghĩa là sẵn sàng khi cơ hội đúng tới.
Steve Jobs đã đúng bởi vì trong một năm sau máy tính Apple đầu tiên ra, đã có trên năm mươi công ti làm sản phẩm tương tự nhưng không công ti nào trong số họ thành công. Cùng điều đó cũng xảy ra với Microsoft khi Bill Gates phát triển MSDOS đầu tiên, vào thời đó không có sản phẩm tương tự nhưng về sau, có nhiều công ti phần mềm đã phát triển hệ điều hành cho các máy tính khác nhưng không công ti nào trong số họ thành công.
Tất nhiên, Facebook có đủ công nhân có kĩ năng để xây dựng một sản phẩm tương tự với Instagram. Nhưng nó KHÔNG là Instagram vì công ti này là công ti đầu tiên trên thị trường có hàng trệu người dùng. Vì ảnh là cấu phần then chốt của Facebook và Instagram là người lãnh đạo trong ảnh cho di động, tốt hơn cả cho Facebook là mua Instagram cho nên nó sẽ có nhiều người dùng để thêm vào danh sách khách hàng của công ti thay vì xây dựng sản phẩm tương tự khác.
Vài năm trước, Google có sản phẩm tên là Google Video để chia sẻ video trên Internet nhưng YouTube là người đầu tiên và rất lớn. Cho dù kĩ thuật là tương tự, nhưng số người dùng là khác nhau. Kĩ thuật là dễ làm nhưng có khách hàng là KHÔNG dễ dàng cho nên Google bỏ Google Video của nó và mua You Tube với giá $1.6 tỉ đô la. Trong kinh doanh, thành công then chốt KHÔNG là kĩ thuật mà là số khách hàng và người dùng.
Nếu bạn tới với một ý tưởng mới và xây dựng cái gì đó mà không ai có và có nhiều khách hàng, cơ hội cho các công ti lớn quan tâm trong việc mua công ti của bạn là rất cao. Ngày nay việc mua bán là một phần của kinh doanh toàn cầu, khi các công ti toàn cầu đang chuyển vào thị trường khu vực, họ thường mua công ti địa phương mà đã có nhiều người dùng thay vì xây dựng cái gì đó mới để cạnh tranh. Đó là lí do tại sao Instagram trị giá $1 tỉ đô la và You Tube trị giá $ 1.6 tỉ đô la và công ti của bạn có thể là công ti tiếp, nếu bạn sẵn sàng khi cơ hội đúng tới.
Theo blog của John Vu

Sử dụng Log4Net trong C#

Sử dụng Log4Net trong C#

I/ Log4net là gì?

- Log4net là một công cụ giúp người lập trình ghi lại những thông tin trong lúc chạy ứng dụng. Nó chính là một phiên bản chuyển thể từ log4j và vẫn tiếp tục được phát triển kể từ năm 2001. Trong trường hợp ứng dụng của bạn có lỗi mà vẫn không tìm được nguyên nhân, log4net có thể là vị cứu tinh để giúp bạn xác định nơi gây lỗi. Ngoài ra, Log4net còn có thể thay đổi trạng thái log lúc chương trình chạy mà không cần ngừng chương trình. Bên cạnh đó, khi sử dụng log4net sẽ không ảnh hưởng đáng kể đến performance của ứng dụng, log4net còn được thiết kế với tính flexibility rất cao, chúng ta có thể mở rộng và thêm thắt những thứ mình muốn vào thư viện log4net, chẳng hạn như cách thức log, định dạng log, …

(Các bạn có thể download source code sample ở đây)

II/ Tại sao lại sử dụng log4net – lợi ích của log4net

- Như tôi nói ở trên, có những trường hợp nếu không có log4net bạn sẽ không thể nào giải quyết được. Giả sử một ngày đẹp trời bạn kí được hợp đồng béo bở làm phần mềm cho một khách hàng lớn và khó tính. Vì là một công ty lớn nên security của họ rất cao. Khi deploy chương trình cho người ta, bạn phải hẹn trước và phải qua nhiều cửa kiểm tra nghiêm ngặt. Những máy chỉ được cài đặt chương trình bạn viết cho họ và không được cài bất cứ cái gì khác. Như vậy khi sử dụng, nếu chương trình của bạn có lỗi thì làm sao để tìm nguyên nhân? Cùng lắm thì bên khách hàng sẽ chụp màn hình lỗi hoặc email đại khái cho bạn, và với những thông tin chung chung như vậy sẽ rất khó để bạn khắc phục. Ngoài ra bạn không thể cài VS.NET 2005 lên máy khách hàng hoặc tới tận nơi để debug. Nhưng nếu có sử dụng log4net, thông tin về quá trình chạy sẽ được ghi lại trên file hoặc thậm chí email cho bạn. Khi đó bạn sẽ dễ dàng tìm hiểu giải quyết vấn đề trên, và nhanh hay chậm tùy thuộc vào bạn thêm những đoạn log cụ thể và chính xác như thế nào trong code.

- Thêm một ví dụ nữa mà tôi đã từng gặp phải, đó là một project liên quan đến Webservice. Nhóm tôi phải làm một webservice để đọc thông tin trên server và trả kết quả về phía chương trình desktop. Quá trình đọc và tính toán dữ liệu trên server khá phức tạp và qua rất nhiều bước và hầu như không thể debug được. (thực ra là có thể debug được bằng cách sử dụng remote debugger, nhưng sau này tôi mới biết). Nhờ vào log4net, tôi ghi lại những bước tính toán, giá trị các biến trong một lần gọi hàm webservice và từ đó đã fix được khá nhiều bug khó.
Dù bạn là một người kĩ tính đến cỡ nào, bạn giỏi lập trình đến mức nào thì vẫn có thể có những lúc chương trình tung những exception mà bạn không ngờ đến. Sử dụng log4net có thể giúp bạn ghi lại những lần bị lỗi như vậy và từ đó bạn sẽ có cách để fix bug. Hơn nữa cách sử dụng rất dễ và nhanh gọn lẹ thì tại sao ta lại không sử dụng chứ nhị :bbpcuoi5:

III/ Sử dụng như thế nào?

- Trong bài viết này, tôi sẽ giới thiệu cách sử dụng log4net cho một window application và sẽ nói đến cách config cho log4net ghi thông tin log ra file bằng một file App.config. Thực ra đối với web application thì cách sử dụng hoàn toàn tương tự. Chỉ có một số trường hợp file log của bạn không sinh ra được vì không đủ quyền. Như các bạn biết thì Web application chạy dưới 1 process bằng quyền của user ASPNET trong Windows, dó đó nếu user này không đủ quyền ghi file vào folder web của bạn thì file log tương ứng cũng có thể không được tạo ra. Nếu bạn áp dụng log4net cho trang web của mình, và thuê 1 host ở VN để đưa code lên nhưng file log không sinh ra, bạn có thể gọi điện hỗ trợ dịch vụ và nhờ họ thêm permisson cho user ASPNET quyền ghi file vào folder web của bạn.

1/ Bước 1: Hãy download version mới nhất của log4net từ website apache. và add reference vào project của bạn. Khi tôi viết bài này thì version mới nhất của log4net là 1.2.10.


2/ Bước 2: Thêm dòng dưới đây vào file AssemblyInfo.cs (Trong folder Property của project)
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4netSample.exe.config", Watch = true)]   //For log4net 1.2.10.0
- Đây là bước mà tôi thường quên nhất :bbpcuoi3:. Thêm đoạn code này vào file assemblyInfo sẽ giúp log4net biết tìm những thông tin cấu hình của nó ở file App.config. Ở đây các bạn thấy là ConfigFile=Log4netSample.exe.config trong khi file config của chúng ta là App.config. Nguyên nhân là do file config của window application sẽ tự động build thànhtên_assembly.config. Vì chương trình của tôi khi build ra sẽ là Log4netSample.exe nên tôi sẽ chọn giá trị làLog4netSample.exe.config cho config file. Đối với Web application bạn sẽ set là Web.config vì file config cho web app sẽ không bị đổi tên.

- Trong web application, thay vì để dòng lệnh config log4net trong Assembly info, ta sẽ để nó trong eventApplication_Start()

3/Bước 3: Nếu project của bạn chưa có file App.config thì bạn hãy thêm vào file App.config. Đây là file cấu hình cho ứng dụng của bạn. Sau đó bạn thêm những cấu hình dưới đây file file App.config.
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections> <log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Log4netSampleLog.txt" /> <appendToFile value="true" /> <rollingStyle value="Size" /> <maxSizeRollBackups value="10" /> <maximumFileSize value="1MB" /> <staticLogFileName value="true" /> <layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender> <root>
<level value="DEBUG" /> <appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>


Giải thích nội dung file cấu hình:
-Trong file cấu hình này, tôi sử dụng RollingFileAppender. Có rất nhiều loại Appender được xây dựng sẵn trong thư viện log4net. Mỗi loại sẽ có công dụng ghi nội dung log vào một nơi khác nhau. Trong đó RollingFileAppender là được sử dụng nhiều nhất và cũng dễ sử dụng nhất :D. Tôi sẽ giải thích những gì tôi nghĩ là khó hiểu nhất :bbpskien:

<file value="Log4netSampleLog.txt">

  • Thông tin log của chúng ta sẽ được ghi vào file Log4netSampleLog.txt, file này sẽ nằm ở thư mục chạy của ứng dụng, cùng cấp với file exe và file .config của chúng ta. Nếu muốn nó lưu file vào chỗ khác chúng ta có thể hardcode đường dẫn ở đây.
<maxsizerollbackups value="10" />

  • Dữ liệu log sẽ được ghi vào file, vì ta đang sử dụng là RollingFileAppender, nên khi kích thước file vượt quá một mức nào đó thì nó sẽ đổi tên file cũ và ghi vào file mới. Tổng số lượng file tối đa sẽ là 10 và những file cũ nhất sẽ bị xóa nếu số lượng file vượt quá 10.

<maximumfilesize value="1MB">

  • Kích thước file log tối đa sẽ là 1MB.

Layout:
  • Đây là phần khá thú vị, những text log mà chúng ta ghi ra sẽ kèm thêm một số thông tin theo như phần định dạng trong layout như ngày tháng, threadId, className, ... Các bạn có thể tùy biến phần layout này để được log output dễ nhìn nhất.



<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
<layout>


Level:
  • Level mặc định sẽ là Debug cho mọi nơi có sử dụng log trong chương trình của bạn. Nghĩa là nếu bạn khai báo như hình, thì mọi chỗ bạn log đều được ghi xuống file vì level DEBUG là level thấp nhất, nhưng nếu chỗ này bạn để làERROR thì chỉ có những log với level cao hơn hoặc bằng ERROR mới được ghi xuống file. Khi deploy chương trình cho khách hàng, thường thì chúng ta sẽ để level default là ERROR, khi sử dụng có lỗi ta sẽ yêu cầu khách hàng sử lại thành DEBUG nếu cần thiết.

<root>
<level value="DEBUG" /> <appender-ref ref="RollingLogFileAppender" />
</root>


- Thông thường người ta sử dụng full name của class (kèm theo đầy đủ namespace) để dùng như loggerName. Cách dùng này rất hợp lý vì chúng ta sẽ biết đoạn log của mình sinh ra từ class nào. Nếu chúng ta không set trong file config, các logger sẽ thừa hưởng level từ cấp trên nó và level cao nhât là root như trong hình. Ví dụ bạn có 2 lớp như sau :MyApp.Service.A và MyApp.Service.A.B thì khi đó sẽ có 2 loggerName tương ứng với 2 name space trên và loggger thứ 2 sẽ thừa hưởng level như logger1. Bạn nên tham khảo thêm phần này ở Logger hierarchy. Có khi chương trình của bạn có sử dụng một library nào đó mà library này lại có sử dụng log4net, khi đó bạn sẽ có nhu cầu tắt log4net cho library đó và đây chính là nơi bạn cần chỉnh sửa. (NHibernate là 1 ví dụ về library có sử dụng log4net)



4/Bước 4:

- a) bạn thêm namespace log4net cho những nơi nào cần sử dụng log4net.
- b) Sau đó thêm đoạn code dưới đây trong lớp nào có sử dụng log4net

private static readonly ILog _logger = LogManager.GetLogger(typeof(TênLớpCủaBạn).Name);

Hoặc bạn có thể sử dụng cách sau đây nếu thích tổng quát

private static readonly ILog logger = LogManager.GetLogger(

          System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);


5/Bước 5
: Trong code của bạn, nơi nào cần log bạn sẽ thêm đoạn code sau đây:

_logger.Debug("Muahahaha");

Hoặc

_logger.Error("Muahahaha");

- Thật ra để tăng tối đa tốc độ, nhóm tác giả khuyên chúng ta nên khai báo một biến boolean để kiểm tra xem có cần log hay không, nếu có thì mới gọi hàm log.

bool isLogEnabled = _logger.IsDebugEnabled;

- Và trong code:
if (isLogEnabled)
{
_logger.Debug("Muaahahaha");
}

- Các bạn thấy tôi có sử dụng _logger.Debug và _logger.Error, như vậy trong trường hợp nào thì sử dụng .Debug, trường hợp nào sử dụng .Error. Theo tôi thì khi nào cần ghi lại những thông tin sẽ giúp chúng ta phát hiện lỗi nếu có thì chúng ta dùng .Debug, những nơi chúng ta try catch Exception thì chúng ta log Error và thông tin log sẽ là StrackTrace của cái Exception đó.

try
{

//Make some error here
} catch(Exception ex) {
_logger.Errror(ex);// Right _logger.Errror(ex.Message);// Wrong. Because most time, the ex.Message is useless.
}

- Ngoài Debug và Error, logger còn có các level khác được xếp theo thứ tự độ ưu tiên. Tùy vào bạn chính config như thế nào mà những đoạn log của bạn có hiện ra hay không.


IV/ Log4net còn có thể làm gì?


- Ngoài khả năng ghi những đoạn log vào file, log4net còn có thể ghi những thông tin log đó vào database, ra console màn hình, email cho chúng ta, thậm chí net send :D. Ngoài ra, với tính mở rất cao, log4net còn cho phép người sử dụng kế thừa mở rộng và thêm thắt. Đối với cá nhân tôi, sử dụng log4net với FileAppender là quá đủ, hiếm khi tôi cần phải viết thêm. Nhưng ai mà biết được sau này sẽ gặp chuyện gì :bbpnodo:. Nếu các bạn muốn tìm hiểu thêm về log4net, hãy lên trang web http://logging.apache.org/log4net và nhớ chia sẽ với tôi những gì bạn biết được :bbpchao:


V/ Khi nào tôi nên dùng log4net?


Ngay sau khi đọc bài này :bbpbtay:

- Hi vọng sau khi đọc bài viết này bạn có thể áp dụng log4net nếu chưa từng sử dụng. Bạn sẽ thấy rằng dùng log4net rất dễ và rất có ích khi ta áp dụng ngay từ những dòng code đầu tiên. Một số người bạn của tôi thường đợi đến lúc viết xong mới bắt đầu thêm log4net khi có yêu cầu, tôi thấy như thế không nên. Theo tôi ta nên tập thói quen sử dụng log4net đúng lúc đúng chỗ và tự giác :bbpsdieu2: cũng giống như đánh răng và tắm rửa mỗi ngày vậy. Thực ra chúng ta có thể không tắm vài ngày, không đánh răng cũng được nếu ở một mình vì chẳng ảnh hưởng đến ai và chẳng ai biết, nhưng đến một lúc nào đó chúng ta sẽ thấy được lợi ích của việc tự giác. :bbptthan:



Tài liệu tham khảo:
http://logging.apache.org/log4net
http://www.codeproject.com/KB/aspnet/log4net.aspx