/*auto readmore*/ /*auto readmore*/ /* an hien script*/ // an hien password /*an hien ma chuong trinh cong tru */ /*Scrollbox thanh cuon*/ /***Nhung CODE***/ /* dòng xanh dòng trắng */ /* https://cdnjs.com/libraries/prism lay thu vien, can vao ten file ma goi 1. copy link vao vi du:prism-python.min.js 2. ten ngon nua la python */ /*=== New posts ===*/ /*header slider*/ /*=== bai viet lien quan===*/ /*===tabcode===*/

[Database-Tự Học SQL] COM2034_SQL Server - Lab 4: Điều Kiện & Vòng Lặp - P2

Ôn lại lý thuyết:

WHILE: Vòng lặp WHILE là việc chạy/thực thi lặp đi lặp lại một đoạn CODE khi điều kiện cụ thể cho trước trả về giá trị là TRUE thì sẽ dừng. Đầu tiên, nó kiểm tra điều kiện và thực hiện một khối câu lệnh nếu điều kiện là đúng.

BREAK: 

  • Dùng để thoát khỏi vòng lặp (BREAK không có bất kỳ đối số nào đi kèm)
  • Nếu có nhiều WHILE lồng nhau thì BREAK sẽ thoát vòng lặp WHILE gần nó nhất
CONTINUE:

  • Bỏ qua khối lệnh sau nó (khối lệnh trong bước lặp hiện tại), và thực hiện bước lặp tiếp theo
  • CONTINUE không có bất kỳ đối số nào đi kèm
Cấu trúc lệnh WHILE


NỘI DUNG: Tìm về vòng lặp WHILE, TRY ... CATCH, RAISERROR

Bài 1:

Dùng vòng WHILE để viết chương trình đơn giản theo yêu cầu:

  • Viết chương trình tính tổng các số chẵn từ 1 tới 10.
  • Viết chương trình tính tổng các số chẵn từ 1 tới 10 nhưng bỏ số 4.

Bài 2:

Sử dụng cơ sở dữ liệu QLDA. Thực hiện các câu truy vấn sau, sử dụng vòng lặp

  • Cho biết thông tin nhân viên (HONV, TENLOT, TENNV) có MaNV là số chẵn.
  • Cho biết thông tin nhân viên (HONV, TENLOT, TENNV) có MaNV là số chẵn nhưng không tính nhân viên có MaNV là 4.

Bài 3:

Quản lý lỗi chương trình 
Thực hiện chèn thêm một dòng dữ liệu vào bảng PhongBan theo 2 bước 
  • Nhận thông báo “Thêm dữ liệu thành công” từ khối Try
  • Chèn sai kiểu dữ liệu cột MaPHG để nhận thông báo lỗi “Thêm dữ liệu thất bại” từ khối Catch
Viết chương trình khai báo biến @chia, thực hiện phép chia @chia cho số 0 và dùng RAISERROR để thông báo lỗi.


THỰC HIỆN:

Bài 1:

Dùng vòng WHILE để viết chương trình đơn giản theo yêu cầu:

  • Viết chương trình tính tổng các số chẵn từ 1 tới 10.
-- Viết chương trình tính tổng các số chẵn từ 1 tới 10
DECLARE @tong INT = 0;
DECLARE @i INT = 1;

WHILE (@i <= 10)
BEGIN
	IF(@i % 2 = 0)
		SET @tong = @tong + @i
	SET @i = @i + 1
END
PRINT @tong

/*
Kết quả là 30 vì:
2
2 + 4 = 6
6 + 6 = 12
12 + 8 = 20
20 + 10 = 30
*/


  • Viết chương trình tính tổng các số chẵn từ 1 tới 10, nếu số chẵn là số 8 thì kết thúc chương trình
Cách 1:
--  Viết chương trình tính tổng các số chẵn từ 1 tới 10, nếu số chẵn là số 8 thì kết thúc chương trình
DECLARE @tong_break INT = 0;
DECLARE @k INT = 1;

WHILE (@k <= 10)
BEGIN
	IF @k = 8
		BREAK

	IF(@k % 2 = 0)
		SET @tong_break = @tong_break + @k
	SET @k = @k + 1
END
PRINT @tong_break

/*
Kết quả là 12 vì:
2
2 + 4 = 6
6 + 6 = 12

Khi k = 8 thì BREAK có nghĩa sẽ kết thúc vòng lặp (vòng lặp gần nó nhất)

*/
Cách 2:
DECLARE @tong_break INT = 0;
DECLARE @k INT = 1;

WHILE (@k <= 10)
BEGIN
	

	IF(@k % 2 = 0)
		IF @k = 8
			BREAK
		ELSE
			SET @tong_break = @tong_break + @k
	SET @k = @k + 1
END
PRINT @tong_break
  
Các bạn đưa ra nhận xét gì về 2 cách trên

  • Viết chương trình tính tổng các số chẵn từ 1 tới 10 nhưng bỏ số 4.
-- Viết chương trình tính tổng các số chẵn từ 1 tới 10 nhưng bỏ số 4.
DECLARE @tong_bo4 INT = 0;
DECLARE @j INT = 1;

WHILE (@j <= 10)
BEGIN
	IF @j = 4 
		BEGIN
			SET @j = @j + 1 -- phải tăng lên đếm lên 1, nếu không sẽ bị lặp vô hạng do biến đếm j = 4 hoài -> lặp tô tận 
			CONTINUE;
		END
	
	IF  (@j % 2= 0)
		SET @tong_bo4= @tong_bo4 + @j
	
	SET @j = @j + 1
END
PRINT @tong_bo4

/*
Kết quả là 26 vì:
Cách hoạt động cũng tương tự như tính tổng, tuy nhiên khi @j = 4, nó tăng lên 1 đơn vị và KHÔNG thực hiện phép cộng với giá trị = 4 này

*/

Bài 2:

Sử dụng cơ sở dữ liệu QLDA. Thực hiện các câu truy vấn sau, sử dụng vòng lặp

Cho biết thông tin nhân viên (HONV, TENLOT, TENNV) có MaNV là số chẵn.


Lấy thông tin và sắp xếp MANV theo thứ tự giảm dần
-- Lấy thông tin và sắp xếp MANV theo thứ tự giảm dần
SELECT MANV 
FROM NHANVIEN
ORDER BY MANV DESC;

Để đảm bảo MANV là INT thì chúng ta nên ép kiểu MANV sang INT, và lấy ra MANV cao nhất
-- Để đảm bảo MANV là INT thì chúng ta nên ép kiểu MANV sang INT, và lấy ra MANV cao nhất
SELECT TOP 1 
	CONVERT(INT, MANV)
FROM NHANVIEN
ORDER BY CONVERT(INT, MANV) DESC

Lấy MANV cao nhất gán vào biến @max_manv, và MANV nhấp nhất gán vào biến @min_manv (1)
-- Lấy MANV cao nhất gán vào biến @max_manv
DECLARE @max_manv INT
SET @max_manv = (SELECT TOP 1 
					CONVERT(INT, MANV)
				FROM NHANVIEN
				ORDER BY CONVERT(INT, MANV) DESC
				)

-- Tương tự lấy MANV nhấp nhất gán vào biến @min_manv
DECLARE @min_manv INT
SET @min_manv = (SELECT TOP 1 
					CONVERT(INT, MANV)
				FROM NHANVIEN
				ORDER BY CONVERT(INT, MANV) ASC
				)
-- HOẶC
DECLARE @min int = (select min(CAST(manv as int)) from NHANVIEN);
DECLARE @max int = (select max(CAST(manv as int)) from NHANVIEN);


Thực hiện theo yêu cầu (phải kết hợp với (1) để chạy nhé các bạn)

-- Thực hiện theo yêu cầu
WHILE (@min_manv < @max_manv)
BEGIN
	IF (@min_manv % 2 = 0)
		BEGIN
			SELECT MANV
				, HONV, TENLOT, TENNV
			FROM NHANVIEN
			WHERE CONVERT(INT, MANV) = @min_manv
		END
	SET @min_manv = @min_manv + 1
END

Noted 1: Với kiểu thực hiện vòng lặp như code trên chương trình chạy có nhiều khi xuất ra các dòng trắng vì MANV không tồn tại trong trường hợp MANV không liên tục,... 

Để khắc phục lỗi đó chúng ta có thể kiểm tra xem @min_manv có tồn trong bảng NHANVIEN thì mới thực hiện

-- Để khắc phục lỗi đó chúng ta có thể kiểm tra xem @min_manv có tồn trong bảng NHANVIEN thì mới thực hiện
WHILE (@min_manv < @max_manv)
BEGIN
	IF (@min_manv % 2 = 0)
		BEGIN
			IF EXISTS(SELECT CONVERT(INT, MANV) FROM NHANVIEN WHERE CONVERT(INT, MANV) = @min_manv) -- kiểm tra sự tồn tại của @min_manv trong bảng NHANVIEN
				SELECT MANV
					, HONV, TENLOT, TENNV
				FROM NHANVIEN
				WHERE (CONVERT(INT, MANV) = @min_manv)
		END
	SET @min_manv = @min_manv + 1
END;


Noted 2: Hai số chẵn kế nhau cách nhau 2 đơn vị, nếu chúng ta đã xác định được số đầu tiên rồi để tìm số chẵn tiếp theo thì chúng ta lấy số đó cộng thêm 2. => Với code trên các bạn xem và thay đổi sao cho hợp lý nhất để chương trình không cần kiểm tra các @min_manv là số lẻ. Như vậy lúc này vòng lặp chúng ta sẽ thực hiện lặp ít hơn,... mà vẫn cho ra kết quả không đổi.

Tham khảo cách KHÔNG DÙNG vòng lặp:

khong dung vong lap
SELECT MANV, TENLOT, TENNV 
FROM NHANVIEN
WHERE CONVERT(INT,MANV) %2 = 0


Cho biết thông tin nhân viên (HONV, TENLOT, TENNV) có MaNV là số chẵn nhưng không tính nhân viên có MaNV là 4.

Cách 1:
-- Cho biết thông tin nhân viên (HONV, TENLOT, TENNV) có MaNV là số chẵn nhưng không tính nhân viên có MaNV là 4
WHILE (@min_manv < @max_manv)
BEGIN
	IF (@min_manv = 4)
		BEGIN
			SET @min_manv = @min_manv + 1
			CONTINUE
		END
	IF (@min_manv % 2 = 0)
		BEGIN
			IF EXISTS(SELECT CONVERT(INT, MANV) FROM NHANVIEN WHERE CONVERT(INT, MANV) = @min_manv) -- kiểm tra sự tồn tại của @min_manv trong bảng NHANVIEN
				SELECT MANV
					, HONV, TENLOT, TENNV
				FROM NHANVIEN
				WHERE (CONVERT(INT, MANV) = @min_manv)
		END
	SET @min_manv = @min_manv + 1
END;

Cách 2:
-- HOẶC
WHILE (@min_manv < @max_manv)
BEGIN
	
	IF (@min_manv % 2 = 0)
		IF @min_manv = 4
			BEGIN
				SET @min_manv = @min_manv + 1
				CONTINUE
			END
		ELSE

			BEGIN
				IF EXISTS(SELECT CONVERT(INT, MANV) FROM NHANVIEN WHERE CONVERT(INT, MANV) = @min_manv) -- kiểm tra sự tồn tại của @min_manv trong bảng NHANVIEN
					SELECT MANV
						, HONV, TENLOT, TENNV
					FROM NHANVIEN
					WHERE (CONVERT(INT, MANV) = @min_manv)
			END
	SET @min_manv = @min_manv + 1
END;

Noted: Các bạn xem xem 2 cách trên, cách nào tối ưu hơn, vì sao

Bài 3:

Quản lý lỗi chương trình 
Thực hiện chèn thêm một dòng dữ liệu vào bảng PhongBan theo 2 bước 
  • Nhận thông báo “Thêm dữ liệu thành công” từ khối Try
  • Chèn sai kiểu dữ liệu cột MaPHG để nhận thông báo lỗi “Thêm dữ liệu thất bại” từ khối Catch
BEGIN TRY
	INSERT PHONGBAN ([TENPHG]
      ,[MAPHG]
      ,[TRPHG]
      ,[NG_NHANCHUC])
	VALUES ('keToan',2,'003','2020-06-02')
	 -- Nếu lệnh chèn thực thi thành công in ra dòng bên dưới
	PRINT 'SUCCESS: Them du lieu THANH CONG'
END TRY
-- Nếu có lỗi xảy ra khi chèn dữ liệu in ra dòng thông báo lỗi cùng với thông tin mã lỗi và thông báo lỗi
BEGIN CATCH
	PRINT 'FAILURE: Them du lieu THAT BAI'
	PRINT 'ERROR ' + CONVERT(varchar, ERROR_NUMBER()) 
		+ ': ' + ERROR_MESSAGE()
END CATCH

Kết quả:
Chạy lần 1 sẽ cho kết quả thành công
(1 row affected)
SUCCESS: Them du lieu THANH CONG

Completion time: 2022-05-25T10:50:40.1103666+07:00

Chạy lần 2 bị thông báo lỗi vì MAPHG đã tồn tại
(0 rows affected)
FAILURE: Them du lieu THAT BAI
ERROR 2627: Violation of PRIMARY KEY constraint 'PK_PhongBan'. Cannot insert duplicate key in object 'dbo.PHONGBAN'. The duplicate key value is (3).

Completion time: 2022-05-25T10:51:03.3769594+07:00

Viết chương trình khai báo biến @chia, thực hiện phép chia @chia cho số 0 và dùng RAISERROR để thông báo lỗi.
BEGIN TRY
	DECLARE @chia INT
	SET @chia = 55/0
END TRY
BEGIN CATCH
	DECLARE
		@ErrMessage NVARCHAR(2048), -- độ dài của chuỗi thông báo lỗi
		@ErrSeverity INT,
		@ErrState INT
		
	SELECT
		@ErrMessage = ERROR_MESSAGE(),
		@ErrSeverity = ERROR_SEVERITY(),
		@ErrState = ERROR_STATE()
		RAISERROR(@ErrMessage, @ErrSeverity, @ErrState) -- thực hiện hiển thị thông báo
END CATCH


Kết quả:

Msg 50000, Level 16, State 1, Line 15
Divide by zero error encountered.

Completion time: 2022-05-25T11:10:58.7629608+07:00


Xong!

No comments:

Post a Comment

/*header slide*/