Chương 3 trình bày những kiến thức về lập trình với cơ sở dữ liệu. Thông qua chương này người học sẽ tìm hiểu về: Biến cục bộ, biến hệ thống, các câu lệnh truy vấn dữ liệu, các hàm thường dùng, cấu trúc điều khiển, cấu trúc lặp, biến kiểu dữ liệu cursor. Mời các bạn cùng tham khảo.
Trang 21.Biến cục bộ
3
Biến cục bộ: dùng để lưu trữ các giá trị tạm
thời trong quá trình tính toán các xử lý bởi sau
khi thoát khỏi chương trình hoặc tắt máy thì giá
trị các biến này không còn trong bộ nhớ nữa
Gán giá trị cho biến:
Dùng SET hoặc SELECT cùng với phép gán (= )
DECLARE @TongSLDat int
SELECT @TongSLDat = SUM(SLDAT)
FROM CTDH
Ví dụ 3:
DECLARE @MinSLDat int, @MaxSLDat int
SELECT @MinSLDat = MIN(SLDAT),
FROM CTDH
Trang 3DECLARE @MinSLDat int, @MaxSLDat int
SELECT @MinSLDat = MIN(SLDAT),
@MaxSLDat = MAX(SLDAT), FROM CTHDON
PRINT „Số lượng đặt thấp nhất là:‟
PRINT @MinSLDat
PRINT „Số lượng đặt cao nhất là:‟
Trong Transaction-SQL phạm vi hoạt động của biến chỉ
nằm trong một thủ tục nội tại (stored procedure) hoặc một
lô (batch) chứa các câu lệnh mà biến đã được khai báo
bên trong đó
Lô được xem như một nhóm tập hợp của một hoặc nhiều
câu lệnh Transaction-SQL sẽ được biên dịch đồng thời
cùng lúc tại SQL Server
Một từ khoá GO chỉ định kết thúc 1 lô
6
1.Biến cục bộ
Trang 4Do các câu lệnh trong một lô được biên dịch tại SQL
Server vì thế khi có ít nhất 1 lệnh bên trong lô có lỗi về cú
pháp lúc biên dịch thì hệ thống sẽ không có lệnh nào được
thực thi bên trong lô đó
Ví dụ:
SELECT * FROM NHACC ORDER BY TenNhaCC
INSERT INTO NHACC
(„C01‟, „Nguyen Van A‟, ‟87 Ly Tu Trong‟,„0903.123456‟)
SELECT * FROM VATTU ORDER BY Tenvtu DESC
GO (thiếu từ khoá VALUES) thì các lệnh SELECT bên trong lô này 7
không được thực hiện
1.Biến cục bộ
Đối với các lỗi khi thực hiện (run-time) bên trong 1 lô nếu
trường hợp các lỗi vi phạm ràng buộc toàn vẹn dữ liệu thì
hệ thống SQL Server chỉ ngưng lại câu lệnh gây lỗi và thực
hiện tiếp các lệnh bên trong lô đó
Ví dụ:
SELECT * FROM NHACC
ORDER BY TenNhaCC
INSERT INTO NHACC
VALUES („C01‟, „Nguyen Van A‟, ‟87 Ly Tu Trong‟,„0903.123456‟)
SELECT * FROM VATTU
(mặc dù vi phạm ràng buộc toàn vẹn trong INSERT (giả sử trùng khoá chính ở cột MaNCC) nhưng các lệnh SELECT bên trong lô này vẫn được thực hiện bình thường
1.Biến cục bộ
Trang 5 Ví dụ:
DECLARE @NgayDH datetime
SELECT @NgayDH = MAX(NGAYDH)
FROM DONDH
GO
PRINT “ngay dat hang gan nhat: ” + convert(char(12),
@ngaydh)
GO HT sẽ báo lỗi vì có thêm từ khoá GO ở giữa 2
lệnh SELECT và PRINT Bởi vì khi đó các lệnh này được chia làm 2 lô và lô thứ hai sẽ không hiểu biến @ngaydh đã được khai báo trong lô thứ 1
1.Biến cục bộ
2.Biến hệ thống
Các biến hệ thống trong SQL Server luôn bắt đầu bằng 2
chữ @@
Giá trị mà chúng ta đang lưu trữ do hệ thống SQL cung cấp
Người lập trình không can thiệp trực tiếp để gán giá trị vào
các biến hệ thống
10
Trang 6Tên biến kiểu trả
về
Dùng để trả về
connections số nguyên Tổng số các kết nối vào SQL Server từ khi nó được
khởi động Error số nguyên số mã lỗi của câu lệnh thực hiện gần nhất Khi một
lệnh thực hiện thành công thì biến này có giá trị là 0 Language chuỗi Tên ngôn ngữ mà hệ thống SQL đag sử dụng Mặc
định là US_English RowCount số nguyên Tổng số mẩu tin được tác động vào câu lệnh truy vấn
gần nhất ServerName chuỗi Tên của máy tính cục bộ được cài đặt trong SQL
Server ServiceName chuỗi Tên dịch vụ kèm theo bên dưới SQL Server
Fetch_Status số nguyên Trạng thái của việc đọc dữ liệu trong bảng theo cơ chế
dòng mẩu tin (cursor) Khi dữ liệu đọc mẩu tin thành công thì biến này có giá trị là 0
Version chuỗi Phiên bản, ngày của phẩm SQL Server và loại CPU
SET PHATRAM = PHANTRAM + 5
(Trả về tổng số mẩu tin có MAVTU bắt đầu bằng chữ
2.Biến hệ thống
Trang 73.Các câu lệnh truy vấn dữ liệu
• Biểu thức boolean xác định dòng nào sẽ được rút trích
• Nối các biểu thức: AND, OR, và NOT
• Phép toán: , , , , , , LIKE và BETWEEN
Trang 8Lấy tất cả các cột của quan hệ kết quả
SELECT MANV, HONV, TENLOT + TENNV as HOTEN
FROM NHANVIEN
WHERE PHG=5 AND PHAI=„Nam‟
SELECT MANV, LUONG*1.1 AS „LUONG10%‟
FROM NHANVIEN
WHERE PHG=5 AND PHAI=„Nam‟
Mở rộng Tên bí danh
Trang 10WHERE MA_NQL IS NULL
SELECT MANV, TENNV FROM NHANVIEN
WHERE MA_NQL IS NOT NULL
Trang 123.2.Truy vấn lồng
Chỉ một câu lệnh truy vấn lựa chọn (SELECT)
được lồng vào các câu lệnh truy vấn khác
nhằm thực hiện các truy vấn tính toán phức
tạp Khi sử dụng đến truy vấn lống chúng ta
cần lưu tâm đến một vài yếu tố sau:
Cần mở và đóng ngoặc đơn cho câu lệnh truy vấn con
Chúng ta chỉ được phép tham chiếu đến tên một cột hoặc
một biểu thức sẽ trả về giá trị trong truy vấn con
Kết quả truy vấn con có thể trả về là một giá trị đơn lẻ hoặc
một danh sách các giá trị
Cấp độ lồng nhau của các truy vấn con bên trong SQL
Server là không giới hạn
23
Mệnh đề WHERE của câu truy vấn cha
<biểu thức> <so sánh tập hợp> <truy vấn con>
So sánh tập hợp thường đi cùng với một số toán tử
• = ,<>, >=, <=, <, >
• IN, NOT IN
• ALL
• ANY hoặc SOME
Kiểm tra sự tồn tại
• EXISTS
• NOT EXISTS
24
3.2.Truy vấn lồng
Trang 13Truy vấn con trả về một giá trị đơn : là truy vấn mà kết
qủa trả về của nó luôn đảm bảo chỉ là một giá trị đơn
Ví dụ: để biết được danh sách các đơn đặt hàng gần đây
Truy vấn con trả về danh sách các giá trị: trả về của
nó là danh sách các giá trị hay còn gọi là một tập hợp
các phần tử Toán tử IN sẽ được sử dụng để so sánh
truy vấn con dạng này
Ví dụ 1: để biết nhà cung cấp nào mà công ty đã đặt hàng trong
Trang 14Đâu đảm bảo rằng trong tháng 01/2002 công
ty chỉ đặt hàng cho 2 nhà cung cấp C01 và
C03 Do đó để luôn luôn có được danh sách họ
tên các nhà cung cấp mà công ty đã đặt trong
tháng 01-2002 chúng ta thực hiện truy vấn con
• Mệnh đề WHERE của truy vấn con không tham chiếu đến thuộc tính
của các quan hệ trong mệnh đề FROM ở truy vấn cha
• Khi thực hiện, câu truy vấn con sẽ được thực hiện trước
Lồng tương quan
• Mệnh đề WHERE của truy vấn con tham chiếu ít nhất một thuộc tính
của các quan hệ trong mệnh đề FROM ở truy vấn cha
• Khi thực hiện, câu truy vấn con sẽ được thực hiện nhiều lần, mỗi lần
tương ứng với một bộ của truy vấn cha
28
3.2.Truy vấn lồng
Trang 15SELECT TenNCC, DienThoai
WHERE Covert(char(7), NgayDH, 21) = “2007-01”
AND NHACC.MaNCC = DONDH.MaNCC)
30
Lồng tương quan
3.2.Truy vấn lồng
Trang 16Ví dụ
Ví dụ 2: Danh sách các nhà cung cấp nào mà công ty
chưa bao giờ đặt hàng:
SELECT TenNhaCC, DienThoai
Trang 173.3.Hàm kết hợp
COUNT
COUNT(*) đếm số dòng
COUNT(<tên thuộc tính>) đếm số giá trị khác
NULL của thuộc tính
COUNT(DISTINCT <tên thuộc tính>) đếm số giá trị
khác nhau và khác NULL của thuộc tính
Trang 18Ví dụ
Tìm tổng lương, lương cao nhất, lương thấp
nhất và lương trung bình của các nhân viên
Cho biết số lượng nhân viên của phòng
FROM NHANVIEN, PHONGBAN
WHERE PHG=MAPHG AND TENPHG= ‘Nghiên cứu’
3.4.Gom nhóm
Cú pháp
Sau khi gom nhóm
Mỗi nhóm các bộ sẽ có cùng giá trị tại các thuộc tính
gom nhóm
36
SELECT <danh sách các cột>
FROM <danh sách các bảng>
WHERE <điều kiện>
GROUP BY <danh sách các cột gom nhóm>
Trang 19Ví dụ
Cho biết số lượng nhân viên của từng phòng ban
37
SELECT PHG, COUNT(*) AS SL_NV FROM NHANVIEN
GROUP BY PHG
SELECT TENPHG, COUNT(*) AS SL_NV FROM NHANVIEN, PHONGBAN
WHERE PHG=MAPHG GROUP BY TENPHG
Ví dụ
Với mỗi nhân viên cho biết mã số, họ tên, số
lượng đề án và tổng thời gian mà họ tham gia
38
SELECT MA_NVIEN, COUNT(*) AS SL_DA,
SUM(THOIGIAN) AS TONG_TG
GROUP BY MA_NVIEN
SELECT MA_NVIEN ,HONV, TENNV, COUNT(*) AS SL_DA,
SUM(THOIGIAN) AS TONG_TG FROM PHANCONG, NHANVIEN
WHERE MA_NVIEN=MANV
GROUP BY MA_NVIEN, HONV, TENNV
Trang 203.5.Điều kiện trên nhóm
WHERE <điều kiện>
GROUP BY <danh sách các cột gom nhóm>
HAVING <điều kiện trên nhóm>
SELECT MA_NVIEN, COUNT(*) as SLDA
GROUP BY MA_NVIEN
HAVING COUNT(*) >= 2
Ví dụ
Cho biết những phòng ban (TENPHG) có lương
trung bình của các nhân viên lớn lơn 20000
SELECT PHG, AVG(LUONG) AS LUONG_TB
FROM NHANVIEN
GROUP BY PHG
HAVINGAVG(LUONG) > 20000
SELECT TENPHG, AVG(LUONG) AS LUONG_TB
FROM NHANVIEN, PHONGBAN
WHERE PHG=MAPHG
GROUP BY TENPHG
HAVINGAVG(LUONG) > 20000 40
Trang 21HAVING MAX ( AVG (LUONG))
SELECT PHG, AVG (LUONG) AS
LUONG_TB
FROM NHANVIEN
GROUP BY PHG
HAVING AVG (LUONG) >= ALL (
SELECT AVG (LUONG)
[WHERE <điều kiện>]
[GROUP BY <các thuộc tính gom nhóm>]
[HAVING <điều kiện trên nhóm>]
[ORDER BY <các thuộc tính sắp thứ tự>]
Trang 22 Danh sách các thuộc tính cần thêm dữ liệu
Danh sách các giá trị tương ứng
Cú pháp (thêm 1 dòng)
44
INSERT INTO <tên bảng>(<danh sách các thuộc tính>)
VALUES (<danh sách các giá trị>)
Trang 23Ví dụ
45
INSERT INTO NHANVIEN(HONV, TENLOT, TENNV, MANV)
VALUES („Le‟, „Van‟, „Tuyen‟, „635635635‟)
INSERT INTO NHANVIEN
VALUES („Le‟, „Van‟, „Tuyen‟, „635635635‟, ‟12/30/1952‟, ‟98 HV‟, „Nam‟,
„37000‟, 4)
INSERT INTO NHANVIEN(HONV, TENLOT, TENNV, MANV, DCHI)
VALUES („Le‟, „Van‟, „Tuyen‟, „635635635‟, NULL )
Nhận xét
Thứ tự các giá trị phải trùng với thứ tự các cột
Có thể thêm giá trị NULL ở những thuộc tính
không là khóa chính và NOT NULL
Câu lệnh INSERT sẽ gặp lỗi nếu vi phạm RBTV
• Khóa chính
• Tham chiếu
• NOT NULL - các thuộc tính có ràng buộc NOT NULL
3.6.1.Thêm (insert)
Trang 24 Cú pháp (thêm nhiều dòng)
47
INSERT INTO <tên bảng>(<danh sách các thuộc tính>)
<câu truy vấn con>
INSERT INTO THONGKE_PB(TENPHG, SL_NV, LUONG_TC)
SELECT TENPHG, COUNT(MANV), SUM(LUONG)
FROM NHANVIEN, PHONGBAN
WHERE PHG=MAPHG
GROUP BY TENPHG
Trang 25 Dùng để xóa các dòng của bảng
Cú pháp:
Ví dụ:
49
DELETE FROM <tên bảng>
[WHERE <điều kiện>]
DELETE FROM NHANVIEN WHERE MANV=„345345345‟
DELETE FROM NHANVIEN
Trang 26 Lệnh DELETE có thể gây ra vi phạm RB tham chiếu
• Không cho xóa
• Xóa luôn những dòng có giá trị đang tham chiếu đến
SET <tên thuộc tính>=<giá trị mới>,
<tên thuộc tính>=<giá trị mới>,
…
[WHERE <điều kiện>]
Trang 27Ví dụ
53
UPDATE NHANVIEN SET NGSINH=‟08/12/1965‟
WHERE MANV=„333445555‟
UPDATE NHANVIEN SET LUONG=LUONG*1.1
Những dòng thỏa điều kiện tại mệnh đề WHERE sẽ
được cập nhật giá trị mới
Nếu không chỉ định điều kiện ở mệnh đề WHERE, tất
cả các dòng trong bảng sẽ bị cập nhật
Lệnh UPDATE có thể gây ra vi phạm RB tham chiếu
• Không cho sửa
• Sửa luôn những dòng có giá trị đang tham chiếu đến
– CASCADE
54
3.6.3 Sửa (update)
Trang 284.Các làm thường dùng
Các hàm chuyển đổi kiểu dữ liệu
Các hàm về ngày
55
4.1.Các hàm chuyển đổi kiểu dữ liệu
Hàm CAST : chuyển đổi một biểu thức nào đó
sang một kiểu dữ liệu mong muốn
Cú pháp:
CAST (Biểu_thức AS kiểu_dữ_liệu)
Ví dụ:
SELECT MaVTU, TenVT,
TyLe = CAST(PHANTRAM AS VARCHAR(3)) + ‘%’
FROM VATTU
56
Trang 29 Hàm CONVERT : chuyển đổi một biểu thức nào đó sang
một kiểu dữ liệu bất kỳ mong muốn nhưng có thể theo
Bảng chuyển mô tả viết tắt của đơn vị
STT Định dạng năm (yyyy) Hiển thị dữ liệu
15 21 hoặc 121 Yyyy-mm-dd hh:mi:ss.mmm
16 20 hoặc 120 Yyyy-mm-dd hh:mi:ss 58
58
Trang 30 Hàm STR : chuyển đổi kiểu dữ liệu số sang kiểu dữ liệu
chuỗi Phải đảm bảo đủ khoảng trắng để chứa các ký số
khi chuyển sang kiểu dữ liệu chuỗi
Cú pháp:
STR(Số_thực, Số_ký_tự[, Số_lẻ])
Ví dụ:
SELECT TenVT, SLNhap = STR(SLNhap, 5) + „ ‟ + DVTinh
WHERE VATTU.MaVT = CTPNHAP.MaVT
Hàm trả về vị trí đầu tiên tính từ vị trí start tại đó
chuỗi string1 xuất hiện trong chuỗi string2
Hàm LEFT: LEFT(string,number)
Hàm trích ra number ký tự từ chuỗi string tính từ
phía bên trái
4.1.Các hàm chuyển đổi kiểu dữ liệu
Trang 314.2.Các hàm trên dữ liệu kiểu chuỗi
Hàm LEN: LEN(string)
Hàm trả về độ dài của chuỗi string
Hàm LOWER : LOWER(string)
Hàm có chức năng chuyển chuỗi string thành chữ
thường, kết quả được trả về cho hàm
Hàm trả về một chuỗi có được bằng cách thay thế các
chuỗi string2 trong chuỗi string1 bởi chuỗi string3
Hàm REVERSE: REVERSE(string)
Hàm trả về chuỗi đảo ngược của chuỗi string
Hàm RIGHT: RIGHT(string, number)
Hàm trích ra number ký tự từ chuỗi string tính từ phía
Trang 32Hàm trả về mã UNICODE của ký tự đầu tiên bên trái
của chuỗi UnicodeString
63
4.2.Các hàm trên dữ liệu kiểu chuỗi
4.4.Các hàm về ngày
DATEDIFF : trả về 1 số nguyên khoảng cách của hai ngày
theo một đơn vị thời gian bất kỳ
DATEDIFF(don_vi, ngay1, ngay2)
Trang 33 DATENAME: trả về một chuỗi thời gian đại diện của 1
ngày chỉ định theo một đơn vị thời gian bất kỳ
DATEPART: trả về 1 số nguyên chỉ định thời gian đại diện của
1 ngày theo một đơn vị thời gian bất kỳ
Trang 34WHEN <giá trị> THEN <biểu thức>
WHEN <giá trị> THEN <biểu thức>
…
[ELSE <biểu thức>]
END
Trang 35Ví dụ 1: Cho biết họ tên các nhân viên đã đến tuổi về
hưu (nam 60 tuổi, nữ 55 tuổi)
69
SELECT HONV, TENNV
FROM NHANVIEN
WHERE YEAR ( GETDATE ()) – YEAR (NGSINH) >= ( CASE PHAI
WHEN 'Nam' THEN 60
WHEN 'Nu' THEN 55 END )
5.1 Cấu trúc Case
Ví dụ 2: hiển thị danh sách các sản phẩm có trong bảng
SANPHAM theo từng loại hàng
SELECT MAVTU, TenVTU, Loai = CASE LEFT(MAVTU,2)
FROM VATTU
70
5.1 Cấu trúc Case
Trang 36Ví dụ 3: Giảm giá bán hàng trong tháng 2-2007 theo quy
tắc sau: Nếu số lượng hàng <= 2 thì không giảm giá, Nếu
số lượng hàng từ 3 đến 10 thì giảm 10%, Nếu số lượng
hàng > 10 thì giảm 20%
UPDATE CTPXUAT
SET DGXuat = CASE
WHEN SLXUAT <=2 THEN DGXuat WHEN SLXUAT BETWEEN 3 AND 10 THEN DGXuat * 0.9 ELSE DGXuat*0.8
END
FROM CTPXUAT, PXUAT
WHERE CTPXUAT.SoPX = PXUAT.SoPX
AND Convert(char(7), NgayXuat, 21) = “2007-02” 71
Trang 37 Ví dụ: Cho biết vật tư nào đã bán ra với số lượng nhiều hơn
4 không? Nếu có thì hiển thị danh sách đó ra, ngược lại thì
thông báo chưa bán vật tư nào nhiều hơn 4
IF (SELECT COUNT(*) FROM CTPXUAT WHERE
SLXUAT>4)>0
BEGIN
Print “Danh sách các hàng hoá bán ra với số lượng lớn hơn 4”
SELECT CTPXUAT.MAVT, TENVT, SLXUAT
FROM CTPXUAT, VATTU
WHERE CTPXUAT.MaVT = VATTU.MaVT
Các_lệnh_lặp END
6.Cấu trúc lặp
Trang 38Ví dụ 1: Để in ra 10 số nguyên dương bắt đầu từ 100
DECLARE @Songuyen INT
SET @Songuyen = 100
WHILE (@Songuyen < 110)
BEGIN
Print “Số nguyên: ” + convert(char(3), @songuyen)
SET @Songuyen = @Songuyen +1
Trang 39Từ khoá BREAK lồng vào cấu trúc WHILE để có thể kết
thúc việc lặp của các lệnh bên trong vòng lặp
DECLARE @Songuyen int
Thực hiện giống ví dụ trước, nhưng muốn in sót số nguyên
105 Chúng ta sử dụng cấu trúc lặp WHILE như sau:
DECLARE @Songuyen int
Trang 407.Kiểu dữ liệu cursor
CSDL quan hệ thường làm việc trên dữ liệu của nhiều
dòng mẩu tin – còn gọi là các bộ mẩu tin Lệnh
SELECT kết quả luôn trả về nhiều mẩu tin hơn là một
mẩu tin
Tuy nhiên trong thực tế, có những trường hợp cần xử
lý vấn đề trên một mẩu tin hoặc trên nhiều mẩu tin
cùng thời gian với hình thức tính toán khác nhau Để
đáp ứng được yêu cầu này SQL Server tạo ra một
kiểu dữ liệu đó chính là kiểu cursor
80