1- Giới thiệu
Tài liệu này hướng dẫn cho những người mới bắt đầu làm quen với SQL. Tài liệu hướng dẫn dựa trên:-
ORACLE 11g
- Ngôn ngữ SQL
- Ngữ pháp SQL (Ngữ pháp cơ bản, tiêu chuẩn cho mọi loại DB)
- Ngữ pháp SQL riêng của Oracle.
2- Bắt đầu nhanh
Ví dụ truy vấn (Query)
Với Oracle, tốt nhất bạn sử dụng một công cụ trực quan, ở đây tôi sử dụng PL/SQL Developer.
3- Một số "thứ" đặc biệt của Oracle
Trước hết chúng ta cần tìm hiểu một chút về một số "thứ" đặc biệt của Oracle. Nó có thể không phải là tiêu chuẩn của các DB khác.3.1 - Dual
Dual giống như một bảng ảo, nó có tại mọi SCHEMA. Và vì vậy bạn có thể truy vấn nó giống một bảng thông thường.[Select * from Dual;
Select 'Dual is special table in Oracle' Column_Title From Dual;]

3.2- Sequence
Sequence là một đối tượng để tạo ra các số tăng dần.Ví dụ tạo ra một Sequence có tên My_Sequence.
[-- Tạo mới một Sequence có tên My_Sequence;
Create Sequence My_Sequence;
]
Lúc đó trên công cụ trực quan bạn có thể nhìn thấy Sequence bạn vừa tạo ra.

[-- Mỗi lần gọi Nextval giá trị của My_Sequence sẽ tăng dần.
-- Hãy thử thực thi lệnh này vài lần.
Select My_Sequence.Nextval From Dual;
-- Bạn có thể sử dụng Currval để lấy ra giá trị hiện thời của My_Sequence.
Select My_Sequence.Currval From Dual;]

4- Các lệnh PL/SQL cơ bản
Ở đây tôi giới thiệu tổng quan về các lệnh cơ bản của PL/SQL. Bạn sẽ hiểu hơn về nó thông qua các ví dụ ở các phần tiếp theo.4.1- Lệnh If-elsif-else
Cú pháp:[
IF <điều kiện 1> THEN
Công việc 1;
[ELSIF <điều kiện 2> THEN
Công việc 2;
]
[ELSE
Công việc n + 1;
]
END IF;
]
Ví dụ:
[
If v_Option = 1 Then
v_Action := 'Run';
Elsif v_Option = 2 Then
v_Action := 'Backup';
Elsif v_Option = 3 Then
v_Action := 'Stop';
Else
v_Action := 'Invalid';
End If;
]
4.2- Vòng lặp không định trước (LOOP)
Cú pháp:[
LOOP
-- Làm gì đó tại đây.
EXIT WHEN <Điều kiện thoát khỏi vòng lặp>;
END LOOP;
]
Ví dụ:
[
x := 0;
Loop
x := x + 1;
y := y - x;
Exit When x > y;
End Loop;
]
4.3- Vòng lặp có định trước (FOR LOOP)
Cú pháp:[
FOR v_Index IN <Cận dưới> .. <Cận trên>
LOOP
-- Làm gì đó tại đây.
END LOOP;
]
Ví dụ:
[
x := 0;
For v_Idx In 1 .. 100 Loop
x := x + 1;
End Loop;
]
4.4- Vòng lặp while (WHILE)
Cú pháp:[
WHILE <Điều kiện> LOOP
-- Làm gì đó tại đây
END LOOP;
]
Ví dụ:
[
v_Text Varchar2(100);
...
While Length(v_Text) < 50 Loop
v_Text := v_Text || '00';
End Loop
]
5- Bắt đầu với PL/SQL sử dụng PL/SQL Developer
Trước hết bạn cần mở PL/SQL Developer và đăng nhập vào
Trên PL/SQL Developer tạo mới một cửa sổ SQL:
[
Declare
v_Result Number;
-- Khai báo một biến có giá trị 50
v_a Number := 50;
-- Khai báo một biến có giá trị 100
v_b Number := 100;
Begin
-- In ra màn hình Console
Dbms_Output.Put_Line(
'v_a= '
|| v_a);
-- In ra màn hình Console
Dbms_Output.Put_Line(
'v_b= '
|| v_b);
-- Tính tổng
v_Result := v_a + v_b;
-- In ra màn hình Console
Dbms_Output.Put_Line(
'v_Result= '
|| v_Result);
End
;
]
Nhấn biểu tượng Tam giác màu xanh (như ảnh) hoặc nhấn F8 để thực thi đoạn code.
Mở sang Tab Ouput xem kết quả chạy ví dụ:
6- Các kiểu dữ liệu thông dụng và khai báo
6.1- Kiểu dữ liệu số
NUMBER(prec, scale) Kiểu dấu chấm cố định (Fixed-point) với giá trị tuyệt đối từ 1E-130 tới (không bao gồm) 1.0E126. Một biến NUMBER cũng có thể mô tả 0.
DECIMAL(prec, scale) Kiểu dấu chấm cố định, tiêu chuẩn IBM với độ chính xác tối đa 38 số thập phân.
NUMERIC(pre, secale) Loại số thực (Floating type) với độ chính xác tối đa 38 số thập phân.
FLOAT Loại số chấm động, số thực tiêu chuẩn ANSI và IBM với độ chính xác tối đa 126 số nhị phân (khoảng 38 số thập phân).
INT Kiểu số nguyên, tiêu chuẩn ANSI với độ chính xác tối đa 38 chữ số thập phân
INTEGER Kiểu số nguyên, tiêu chuẩn ANSI và IBM với độ chính xác 38 chữ số thập phân
Các kiểu số thông dụng nhất:
Kiểu số Khai báo sử dụng
Number v_Amount Number(15,2) hoặc v_Salary Number;
Integer v_Age Integer;
Float v_Amount Float;
Double
Real
6.2- Kiểu text
Thông dụng nhất:
Kiểu text Khai báo sử dụng
Varchar2 v_First_Name Varchar2(32);
NVarchar2 v_First_Name NVarchar2(32);
6.3- Kiểu Date/time
Kiểu dữ liệu Khai báo sử dụng
Date v_Birthday Date;
7 - Các câu lệnh truy vấn (Query)
7.1- SQL Select
Câu lệnh
Select là một câu lệnh cơ bản nhất trong SQL, mục đích là truy vấn dữ liệu trong các bảng (Table).
- BTDQUAN: Bảng dữ liệu Danh mục Quận huyện.
[
-- Truy vấn dữ liệu trên bảng BTDQUAN
-- Truy vấn dữ liệu trên bảng BTDQUAN
-- Truy vấn toàn bộ các cột.
Select
*
From
mqsofthaugiang.btdquan;
-- Câu lệnh truy vấn trên và câu lệnh dưới đây là tương đương nhau.
-- Pty là alias (tên bí danh đặt cho bảng BTDQUAN).
Select
qu.*
From
mqsofthaugiang.btdquan qu;
-- Truy vấn một vài cột
-- Có thể liệt kê ra.
Select
qu.maqu, qu.tenqu
From
mqsofthaugiang.btdquan qu;
]
Câu lệnh Distinct được sử dụng cùng với Select, dùng để select các dữ liệu, bỏ qua các dữ liệu trùng nhau. Cú pháp là:
Select
distinct
<column1>, <column2> ....
]
Xem ví dụ:
[
-- Truy vấn Quận huyện
-- Cột mã quận, tên và mã tỉnh thành.
Select
qu.maqu
, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu;
-- Truy vấn các matt trong bảng btdquan.
-- Dữ liệu là nhiều, nhưng trùng nhau.
Select
qu.matt
from
mqsofthaugiang.btdquan qu;
-- Cần sử dụng Distinct để loại bỏ việc trùng lặp.
Select
Distinct
qu.matt
from
mqsofthaugiang.btdquan qu;
]
7.3- SQL Where
Where là câu lệnh nhằm giới hạn phạm vi tìm kiếm. Chẳng hạn bạn muốn tìm kiếm những quận có mã tỉnh thành là 501.matt = 501.
Bạn cần truy vấn trong bảng BTDQU, tại các vị trí có matt= 501
[
-- Truy vấn bảng BTDQU tìm các Quận có kiểu:
-- matt = 501
Select
*
From
mqsofthaugiang.btdquan qu
Where
qu.matt =
501
;
]
7.4- SQL And Or (Và, hoặc)
And và Or là 2 lệnh điều kiện sử dụng trong where:Chẳng hạn bạn muốn tìm danh sách các quận huyện có tên bắt đầu bởi chữ Q và thuộc Tỉnh có mã là 501.
[
-- Câu lệnh tìm kiếm các Quận huyện có tên bắt đầu bởi chữ Q.
Select
qu.maqu, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu
Where
qu.tenquan
Like
'Q%'
;
-- Câu lệnh tìm kiếm các
Quận huyện có tên bắt đầu bởi chữ Q-- và thuộc Tỉnh có mã là 501.
Select
qu.maqu, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu
Where
qu.tenquan
Like
'Q%'
And qu.matt=501;
]
Kết quả chạy các câu truy vấn:
Ví dụ với câu lệnh Or.
[
-- Tìm kiếm các Quận huyện có tên bắt đầu bởi chữ Q hoặc H.
-- và
thuộc Tỉnh có mã là 501Select
qu.maqu, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu
Where
(qu.tenquan
Like
'Q%'
Or qu.tenquan
Like
'H%'
) And qu.matt=501;]
7.5- SQL IN (Trong phạm vi..)
Toán tử IN cho phép kiểm tra một giá trị có thuộc vào một tập hợp cố định các giá trị nào đó không. Và nó có thể làm việc với tất cả các loại kiểu dữ liệu.[
-- Câu lệnh này tìm kiếm các Quận huyện có tên
-- Quận Cẩm Lệ hoặc Quận Liên Chiểu hoặc Quận Thanh Khê.
Select
qu.maqu, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu
Where
qu.tenquan
In
(N
'Quận Cẩm Lệ'
, N
'Quận Liên Chiểu'
, N
'Quận Thanh Khê'
);
]
Kết quả chạy câu lệnh:
7.6- SQL Between (Nằm giữa ...)
[-- Tìm các Quận huyện có mã tỉnh thành trong khoảng từ 500 đến 503.
Select
qu.maqu, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu
Where
(qu.matt
Between
500
And
503);
-- Câu lệnh trên tương đương với:
Select
qu.maqu, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu
Where
(qu.matt
>=
500
And
qu.matt
<=
503);
]
Câu lệnh BETWEEN cũng được sử dụng trong việc giới hạn thời gian. Chẳng hạn bạn tìm kiếm các Quận huyện có ngày cập nhật (ngayud) trong khoảng thời gian từ
01-10-2018 ==> 30-10-2018 (Theo dd-MM-yyyy)
[
-- Câu lệnh này tìm kiếm các Quận huyện có ngày cập nhật trong 1 khoảng thời gian
-- xác định trong mệnh đề where.
-- 01-10-2018 ==> 30-10-2018 (Theo dd-MM-yyyy)
Select
qu.maqu, qu.tenquan, qu.matt, qu.ngayud
,
-- To_Char là một hàm của Oracle.
-- Không dùng cho DB khác.
-- To_Char chuyển kiểu Date sang text
-- Theo một định dạng nào đó ở đây là dd-MM-yyyy
To_Char(
qu.ngayud,
'dd-MM-yyyy'
) NgayCapNhat
From
mqsofthaugiang.btdquan quWhere
-- To_Date là một hàm của Oracle (Có thể ko có trên DB khác)
-- To_Date là hàm chuyển Text thành Date
-- Theo một định dạng nào đó, ở đây là dd-MM-yyyy.
(
qu.ngayud
Between
To_Date(
'01-10-2018'
,
'dd-MM-yyyy'
)
And
To_Date(
'30-10-2018'
,
'dd-MM-yyyy'
)
);
]
Kết quả chạy câu lệnh:7.8- SQL Like (Giống với ...)
Câu lệnh này chúng ta đã làm quen trên một số ví dụ ở trên.7.9- SQL Order By (Sắp xếp bởi)
Việc query dữ liệu cho một tập kết quả, mà có thể nó sắp xếp không như ý muốn, sử dụng Order by để sắp xếp kết quả trả về.[
-- Cú pháp
SELECT
"column_name"
FROM
"table_name"
[
WHERE
"condition"
]
ORDER
BY
"column_name1"
[
ASC
,
DESC
],
"column_name2"
[
ASC
,
DESC
];
-- Ghi chú:
-- ASC: nghĩa là sắp xếp tăng dần (Mặc định)
-- DESC: Nghĩa là sắp xếp giảm dần.
]
[
-- Sắp xếp ưu tiên Mã tỉnh thành tăng dần
-- Sau đó mới tới Tên quận (Cũng tăng dần)
Select
qu.maqu, qu.tenquan, qu.mattFrom
mqsofthaugiang.btdquan quOrder
By
qu.matt
Asc
, qu.tenquan
Asc
;
-- Trong Order BY, ASC là mặc định.
-- Vì vậy có thể ko cần viết ASC.
Select
qu.maqu, qu.tenquan, qu.mattFrom
mqsofthaugiang.btdquan quOrder
By
qu.matt,
qu.tenquan;
-- Sắp xếp ưu tiên Mã tỉnh thành giảm dần
-- Sau đó mới tới Tên quận (Tăng dần)
Select
qu.maqu, qu.tenquan, qu.mattFrom
mqsofthaugiang.btdquan quOrder
By
qu.matt
Desc
,
qu.tenquan Asc
;
]
Order By bao giờ cũng đứng sau where
[
-- Tìm các Quận huyện có tên bắt đầu bởi chữ Q.
-- Sắp xếp giảm dần theo mã Quận.
Select
qu.maqu, qu.tenquan, qu.matt
From
mqsofthaugiang.btdquan qu
Where
qu.tenquan
Like
'Q%'
Order
By
qu.maqu
Desc
;
]
Kết quả chạy câu lệnh:7.10- SQL Group By (Nhóm bởi ...)
Trước hết chúng ta cần hiểu các hàm tổng hợp ( Aggregate Functions) là gì:Sum: Hàm tính tổng
Avg: Hàm lấy trung bình
Count: Hàm tính số lần
Min: Hàm tìm giá trị nhỏ nhất
Max: Hàm tìm giá trị lớn nhất
Câu hỏi đặt ra bạn muốn xem số lượng biên lai, tổng số tiền thu được và số tiền trung bình của mỗi ngày.
[
Select
To_Char(ll.ngay, 'dd-MM-yyyy') ngay,Count(ll.sobienlai) soluongbienlai, -- Số lượng biên lai theo ngày
Sum(ll.sotien) Sum_sotien, -- Tổng số tiền trong ngày
Avg(ll.sotien) Avg_sotien -- Số tiền trung bình trong ngày
From mqsofthaugiang0419.v_ttrvll ll
Group
By
To_Char(ll.ngay, 'dd-MM-yyyy')]
Kết quả:
7.11- SQL Having
Having là một câu lệnh điều kiện của Group by.Giả sử bạn muốn tính tổng số biên lai của các ngày thu tiền trên bảng v_ttrvll và chỉ hiển thị ra những ngày có số biên lai > 100
[
Select
To_Char(ll.ngay, 'dd-MM-yyyy') ngay,Count(ll.sobienlai) soluongbienlai, -- Số lượng biên lai theo ngày
Sum(ll.sotien) Sum_sotien, -- Tổng số tiền trong ngày
Avg(ll.sotien) Avg_sotien -- Số tiền trung bình trong ngày
From mqsofthaugiang0419.v_ttrvll ll
Group
By
To_Char(ll.ngay, 'dd-MM-yyyy')Having
Count
(ll.sobienlai) > 100;
]
Kết quả:
Phân biệt Where & Having
Bạn cần phân biệt Where và Having trong cùng một câu lệnh.
Where là một mệnh đề để lọc bớt dữ liệu trước khi nhóm (Group)
Having là một mệnh đề để lọc bớt dữ liệu sau khi đã nhóm (Group)
8- SQL Join
Đặt ra một tình huống bạn muốn xem Tỉnh thành của một Bệnh nhân (BN) trong bảng BTDBN (Bộ từ điển Bệnh nhân). Bạn có thể thấy matt của BN này. Nhưng đó chỉ là một con số. Muốn biết tên tỉnh thành, bạn phải tra cứu sang bảng BTDTT (Danh mục Tỉnh thành). Việc nối 2 bảng đó với nhau để có một thông tin đầy đủ được gọi là JOIN.Có 4 hình thức Join:
- INNER JOIN (JOIN)
- LEFT OUTER JOIN (LEFT JOIN)
- RIGHT OUTER JOIN (RIGHT JOIN)
- FULL OUTER JOIN (OUTER JOIN)
- CROSS JOIN
8.1- INNER JOIN (Hoặc JOIN)
INNER JOIN từ khóa chọn tất cả các dòng từ hai bảng miễn là có sự ăn khớp dữ liệu giữa các cột trong cả hai bảng.Cú pháp:
[
SELECT
column_name(s)
FROM
table1
INNER
JOIN
table2
ON
table1.column_name=table2.column_name;
-- Có thể thay INNER JOIN bởi JOIN
-- Ý nghĩa và kết quả là như nhau.
SELECT
column_name(s)
FROM
table1
JOIN
table2
ON
table1.column_name=table2.column_name;
]
Ví dụ:[
-- INNER JOIN 2 bảng BTDBN và BTDTT.
Select
bn.mabn, bn.hoten, bn.matt, tt.tenttFrom
mqsofthaugiang.btdbn bn Inner
Join
mqsofthaugiang.btdtt tt On bn.matt=tt.matt
Order
By
bn.hoten;
Cú pháp riêng của Oracle:
[
-- Việc INNER JOIN theo cách viết khác của Oracle thực sự đơn giản.
-- Oracle đẩy điều kiện JOIN hai bảng xuống WHERE.
Select
bn.mabn, bn.hoten, bn.matt, tt.tenttFrom
mqsofthaugiang.btdbn bn, mqsofthaugiang.btdtt tt
Where bn.matt=tt.matt
Order
By
bn.hoten;
8.2- LEFT OUTER JOIN (Hoặc LEFT JOIN)
LEFT OUTER JOIN là từ khóa trả về tất cả các hàng (rows) từ bảng bên trái (table1), với các hàng tương ứng trong bảng bên phải (table2). Chấp nhận cả dữ liệu NULL ở bảng 2.Ví dụ:
[
-- btdbn LEFT OUTER JOIN btdtt
-- Có thể thay thế LEFT OUTER JOIN bởi LEFT JOIN (Ý nghĩa và kết quả là giống nhau)
Select
bn.mabn, bn.hoten, bn.matt, tt.tenttFrom
mqsofthaugiang.btdbn bn Left
Join
mqsofthaugiang.btdtt tt On bn.matt=tt.matt
Order
By
bn.hoten;
Cú pháp riêng của Oracle:
[
-- LEFT OUTER JOIN theo cú pháp khác của Oracle.
-- Oracle đẩy điều kiện LEFT OUTER JOIN hai bảng xuống WHERE.
-- Sử dụng (+) tại Table2.
Select
bn.mabn, bn.hoten, bn.matt, tt.tenttFrom
mqsofthaugiang.btdbn bn
-- Table1
, mqsofthaugiang.btdtt tt -- Table2
Where bn.matt=tt.matt(+)
Order
By
bn.hoten;
8.3- RIGHT OUTER JOIN (Hoặc RIGHT JOIN)
RIGHT OUTER JOIN ngược lại với LEFT OUTER JOIN:8.4- FULL OUTER JOIN (Hoặc OUTER JOIN)
FULL OUTER JOIN là sự kết hợp của LEFT OUTER JOIN và RIGHT OUTER JOIN[
-- Cú pháp: (FULL OUTER JOIN)
-- Có thể viết FULL JOIN
SELECT
columns
FROM
table1
FULL
[
OUTER
]
JOIN
table2
ON
table1.
column
= table2.
column
;
9- Câu truy vấn con (Subquery)
Trong Oracle, một subquery là một truy vấn trong một truy vấn. Bạn có thể tạo các truy vấn con trong câu lệnh SQL của bạn. Những truy vấn con có thể nằm trong mệnh đề WHERE, mệnh đề FROM, hoặc mệnh đề SELECT.9.1- Subquery trong mệnh đề Where
Khá thường xuyên, các subquery sẽ được tìm thấy trong mệnh đề WHERE. Những truy vấn con còn được gọi là truy vấn con lồng nhau.[
Select
Acc.Account_Id
,Acc.Open_Date
,Acc.Product_Cd
,Acc.Avail_Balance
From
Account Acc
Where
Acc.Cust_Id
In
(
Select
Cus.Cust_Id
From
Customer Cus
Where
Cus.Cust_Type_Cd =
'B'
)
9.2- Subquery trong mệnh đề From
Một truy vấn phụ cũng có thể được tìm thấy trong mệnh đề FROM. Chúng được gọi là inline views.[
Select
Cus.Cust_Id
,Cus.Address
,Cus.Fed_Id
,Acc2.Sum_Avail_Balance
From
Customer Cus
,
-- Câu Subquery định nghĩa 1 bảng ảo (inline view)
(
Select
Acc.Cust_Id
,
Sum
(Acc.Avail_Balance)
As
Sum_Avail_Balance
From
Account Acc
Group
By
Acc.Cust_Id) Acc2
Where
Cus.Cust_Id = Acc2.Cust_Id;
9.3- Subquery trong mệnh đề Select
Một truy vấn phụ cũng có thể được tìm thấy trong mệnh đề SELECT.[
Select
Cus.Cust_Id
,Cus.Address
,Cus.Fed_Id
,(
Select
Sum
(Acc.Avail_Balance)
From
Account Acc
Where
Acc.Cust_Id = Cus.Cust_Id)
As
Sum_Avail_Balance
From
Customer Cus;
Bí quyết để đặt một truy vấn phụ trong mệnh đề select là subquery phải trả lại một giá trị duy nhất. Đây là lý do tại sao một các hàm tổng hợp như hàm SUM, COUNT, MIN, hoặc MAX thường được sử dụng trong subquery.
COMMENTS