GIỚI THIỆU CHUNG VỀ SERIES 3 BÀI VIẾT LIÊN QUAN ĐẾN KIỂU DỮ LIỆU:
- Kiểu dữ liệu (Data Type) của một column trong bảng, giúp chúng ta định nghĩa được giá trị mà column đó có thể giữ là gì. Chúng có thể là integer, character, date, time, binary, ...
- Mỗi column trong bảng BẮT BUỘC phải có 2 thành phần:
- Tên
- Kiểu dữ liệu.
- Khi thiết kế database, chúng ta cần xác định được kiểu dữ liệu sẽ lưu trong mỗi column là gì. Kiểu dữ liệu sẽ giúp cho SQL hiểu được chúng ta mong muốn lưu dữ liệu như thế nào trong column tương ứng. Bên cạnh đó, nó cũng xác định cách SQL sẽ tương tác với những dữ liệu đã được lưu trữ.
- Ban đầu mình dự định sẽ viết một bài viết chung để mô tả ngắn gọn hết tất cả các kiểu dữ liệu thường dùng. Tuy nhiên, sau nhiều lần đắn đo, mình cảm thấy có NHIỀU ĐIỀU HAY HO HƠN để viết về các kiểu dữ liệu. Dựa trên kinh nghiệm làm việc thực tế thì mình thấy các bạn sinh viên/fresher/junior NÊN BIẾT những kiến thức này, không đơn giản là chỉ cần nắm được trong MySQL có những kiểu dữ liệu nào, mà chúng ta cũng cần hiểu rõ SỰ KHÁC NHAU giữa những kiểu dữ liệu nhìn có vẻ "TỰA TỰA GIỐNG NHAU". Trường hợp nào thì nên dùng kiểu A, trường hợp nào thì nên dùng kiểu B.
- Do đó, nội dung về "Các kiểu dữ liệu thường dùng nhất trong MySQL" sẽ được chia làm 3 phần:
- Numeric Data Types: BIT, TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT, BOOL, FLOAT, DOUBLE, DECIMAL.
- String Data Types: CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT.
- Date and Time Data Types: DATE, TIME, DATETIME, TIMESTAMP
LƯU Ý:
- Những kiến thức trong bài viết sẽ áp dụng với MySQL version 8.0.32.
- Do đó, nó có thể sẽ không đúng với các version trước đó, hoặc những version trong tương lai của MySQL.
- Nếu các bạn học và thực hành theo những chia sẻ trong series "Fullstack Vỡ Lòng" của mình, thì hãy lưu ý sử dụng MySQL version 8.0.32 nhé.
Trong nội dung bài hôm nay, mình sẽ chia sẻ về "Kiểu dữ liệu dạng số - Numeric Data Types"
Mô tả chung về Numeric Data Types
- Anh em cần lưu ý rằng: Các kiểu dữ liệu có thể có cách đặt tên KHÁC NHAU ở các HỆ QUẢN TRỊ CƠ SỞ DỮ LIỆU KHÁC NHAU.
- Ví dụ: Nhiều bạn đã từng dùng các hệ quản trị cơ sở dữ liệu khác như SQL Server chẳng hạn, khi chuyển sang học MySQL sẽ không thấy kiểu dữ liệu NVARCHAR, UNIQUEIDENTIFIER. Các bạn có thể coi điều là này BÌNH THƯỜNG, giống như ngôn ngữ lập trình vậy đó, Java và C# cùng dùng trong lập trình hướng đối tượng, nhưng cú pháp của nó cũng khác nhau kha khá.
- Cùng là kiểu dữ liệu dạng số, nhưng chúng ta có thể phân tách nhỏ hơn nữa thành 4 KIỂU NHỎ HƠN KHÁC NHAU, bao gồm:
- Bit-Value Type
- Integer Types
- Fixed-Point Types
- Floating-Point Types
1. Bit-Value Type
BIT
- Có rất nhiều bạn HỌC LƯỚT phần này, nên HIỂU NHẦM rằng "khi set 1 cột có kiểu dữ liệu
BIT
, thì giá trị của cột đó chỉ có thể có duy nhất 2 giá trị là0
và1
."- Thực tế, kết luận trên chỉ đúng với trường hợp mặc định, khi ta không set số lượng bit có thể có trong một cột (chỉ có chữ
BIT
, không có phần mở ngoặc đơn đi kèm), hoặc ta set cột đó có kiểu dữ liệu làBIT(1)
- Còn khi ta muốn dùng nhiều hơn 1 bit để lưu các giá trị, thì ta có thể khai báo kiểu dữ liệu của cột đó là
BIT(size)
. Vớisize
là số lượng bit có thể lưu trữ trong một cột. Trong đó,size
có thể có giá trị từ1
đến64
.
- Thực tế, kết luận trên chỉ đúng với trường hợp mặc định, khi ta không set số lượng bit có thể có trong một cột (chỉ có chữ
- Và khi sử dụng giá trị
size
từ2
trở lên, các bạn sinh viên lại thường có thêm một HIỂU LẦM PHỔ BIẾN nữa như sau: - Ví dụ: Khi set một cột trong bảng có kiểu dữ liệu là
BIT(2)
, nhiều bạn nghĩ rằng dữ liệu của chúng sẽ chỉ có thể các giá trị00
,01
,10
,11
-> ĐIỀU NÀY LÀ SAI HOÀN TOÀN- Các bạn có thể thử và kiểm nghiệm, nếu insert vào dữ liệu là
10
thì MySQL sẽ báo lỗi Data too long for column 'X' at row 1. - Lý do là vì: Khi insert giá trị
10
, MySQL đang hiểu đó là số dạng thập phân, chuyển đổi sang dạng nhị phân sẽ có giá trị là1010
, tức là cần dùng 4 bit, nhiều hơn 2 bit so với kiểu dữ liệuBIT(2)
mà bạn đang set. Do đó, nó mới trả về lỗi Data too long for column 'X' at row 1. - Vậy làm sao để chúng ta có thể lưu chuỗi bit có giá trị
10
trong trường hợp này? Trong MySQL, có 2 cách để các bạn làm được việc đó:- Cách 1: Các bạn insert vào cột đó dữ liệu là số
2
ở dạng thập phân. Vì số2
khi chuyển sang nhị phân sẽ có giá trị là10
. Đúng với giá trị mình đang muốn lưu trữ. - Cách 2: Các bạn insert vào cột dữ liệu là
b'10'
. Đây là cú pháp chuẩn trong MySQL để lưu dữ liệu dạng bit.
- Cách 1: Các bạn insert vào cột đó dữ liệu là số
- Nếu sử dụng công cụ dbForge Studio for MySQL để xem dữ liệu, các bạn sẽ thấy, dù dùng Cách 1 hay Cách 2 ở trên thì khi select dữ liệu ta cũng sẽ nhìn thấy con số
2
ở dạng thập phân (Các bạn có thể xem thêm nội dung giới thiệu công cụ dbForge Studio for MySQL tại link sau: Fullstack Vỡ Lòng 03: Công cụ quản trị cơ sở dữ liệu - dbForge Studio for MySQL) - Nếu muốn xem dạng nhị phân của dữ liệu đó, các bạn có thể dùng hàm
BIN()
khiSELECT
:
- Các bạn có thể thử và kiểm nghiệm, nếu insert vào dữ liệu là
- Điểm cần lưu ý thứ 3, đó là nếu bạn insert một giá trị nhị phân có số bit nhỏ hơn
size
, thì MySQL sẽ tự động thêm vào bên trái giá trị nhị phân đó các bit0
.- Ví dụ: insert giá trị
b'101'
vào một cột có kiểu dữ liệu làBIT(6)
, sẽ tương đương với việc insert giá trịb'000101'
- Ví dụ: insert giá trị
2. Integer Types
-
Các bạn sinh viên/fresher/junior hãy ĐẶC BIỆT LƯU Ý phần này nhé, vì khi làm việc với các bạn fresher ở công ty mình, mình thấy các bạn ấy hầu như lúc nào cũng sử dụng
INT
.- Có thể vì nó quen thuộc khi học trên trường, hoặc các bạn không biết ngoài
INT
ra thì còn có các kiểu dữ liệu khác để thể hiện cho Integer nữa. - Tựu chung lại là do các bạn ấy chưa thực sự hiểu khi nào thì nên dùng
INT
, khi nào thì không.
- Có thể vì nó quen thuộc khi học trên trường, hoặc các bạn không biết ngoài
-
Ngoài 2 kiểu dữ liệu Integer tiêu chuẩn mà hệ quản trị cơ sở dữ liệu quan hệ nào cũng có là
INT
vàSMALLINT
, thì MySQL còn hỗ trợ thêm một số kiểu dữ liệu Integer khác như:TINYINT
,MEDIUMINT
vàBIGINT
. -
Có thể thấy ngay sự khác nhau khi nhìn vào phần prefix của các kiểu dữ liệu này:
TINY
: "nhỏ xíu, rất nhỏ"SMALL
: "nhỏ"MEDIUM
: "trung bình"BIG
: "lớn"
-
Và điều này cũng đúng khi chúng ta nhìn vào sự khác nhau giữa phạm vi lưu trữ dữ liệu của chúng:
-
Các bạn hãy ĐẶC BIỆT CHÚ Ý vào cột Storage (Bytes), bởi vì con số này sẽ luôn là cố định, dù cho con số mà bạn lưu trữ có thực sự cần đến 4 bytes hay không.
- Ví dụ: Bạn muốn lưu số
1
, bạn hoàn toàn có thể dùng cả 5 kiểu dữ liệu trên. Tuy nhiên, kiểu dữ liệuBIGINT
sẽ sử dụng 8 bytes để lưu số1
này, trong khiTINYINT
chỉ cần sử dụng 1 bytes
- Ví dụ: Bạn muốn lưu số
-
Thêm vào đó, trong quá trình làm việc thực tế, một điều QUAN TRỌNG các bạn cần phải hiểu đó là lựa chọn kiểu dữ liệu nào trong 5 kiểu trên trong một bài toán.
- Ví dụ:
- Chúng ta có một cột tên là EmployeeCount, dùng để lưu số lượng nhân viên của một công ty.
- Nếu chúng ta sử dụng kiểu dữ liệu
INT
thì sẽ là rất DƯ THỪA. - Bởi vì số lớn nhất mà
INT
có thể lưu lên tới hơn 4 tỷ. - Trong khi công ty lớn nhất trên thế giới hiện tại cũng chỉ có khoảng 2.3 triệu nhân viên (theo Wikipedia)
- Vì vậy, trong bài toán này, thực tế bạn chỉ cần dùng
MEDIUMINT
là đã đủ để lưu thoải mái EmployeeCount, vìMEDIUMINT
có thể lưu các số từ 0 đến hơn 16 triệu
- Ví dụ:
BOOL, BOOLEAN
- Nhiều bạn nghĩ kiểu dữ liệu
BOOL
,BOOLEAN
phải nằm trong nhóm Bit-Value Type chứ. - Nhưng thực tế thì không phải như vậy.
BOOL
vàBOOLEAN
tương tự vớiTINYINT(1)
. Trong đó, Giá trị0
tương ứng vớifalse
. Các giá trịkhác 0
tương ứng vớitrue
. - Ngoài ra, các bạn cũng cần hiểu rõ ràng rằng, các giá trị
TRUE
vàFALSE
chỉ là bí danh tương ứng cho1
và0
, như ở ví dụ dưới đây:
- 2 câu lệnh
SELECT
dưới cùng chỉ ra rằng: phép so sánh2 = TRUE
và2 = FALSE
làfalse
. - Chỉ có
1 = TRUE
và0 = FALSE
, thì mới trả về kết quả làtrue
.
3. Fixed-Point Types và Floating-Point Types
- Mình gom 2 loại này vào chung một mục để so sánh cho các bạn thấy sự khác nhau giữa chúng
- Fixed-Point Types có 2 kiểu dữ liệu đại diện là
DECIMAL
vàNUMERIC
.- Trong MySQL,
NUMERIC
cũng được implemented giống hệtDECIMAL
. Vì vậy, các nội dung phía dưới mình sẽ chỉ mô tả vớiDECIMAL
, các bạn có thể hiểu làNUMERIC
thì cũng như thế.
- Trong MySQL,
- Còn với Floating-Point Types, cũng có 2 kiểu dữ liệu đại diện là
FLOAT
vàDOUBLE
. - Về Phạm vi lưu trữ dữ liệu:
FLOAT
cho phép lưu trữ dữ liệu có giá trị từ-3.402823466E+38
đến-1.175494351E-38
,0
, và từ1.175494351E-38
đến3.402823466E+38
.DOUBLE
cho phép lưu trữ dữ liệu có giá trị từ-1.7976931348623157E+308
đến-2.2250738585072014E-308
,0
, và từ2.2250738585072014E-308
đến1.7976931348623157E+308
.DECIMAL(size, d)
, trong đó:size
là tổng toàn bộ các số kể cả phần nguyên và phần thập phân (tiếng Anh gọi là precision). Giá trị tối đa củasize
là65
. Nếusize
không được khai báo thì mặc định sẽ lấy giá trị10
.d
là tổng các số ở phần thập phân, phía sau dấu chấm (tiếng Anh gọi là scale). Giá trị tối đa củad
là30
. Nếud
không được khai báo thì mặc định sẽ lấy giá trị0
.
- Ngoài phạm vi lưu trữ dữ liệu, thì sự khác nhau lớn nhất giữa
FLOAT
/DOUBLE
vsDECIMAL
là "FLOAT
vàDOUBLE
gây ra vấn đề về việc làm tròn số".-
Ví dụ: Nếu bạn thực hiện phép toán
0.1
+0.2
, bạn sẽ nhận được kết quả là0.30000000000000004
. -
Do đó, thường thì các dữ liệu về tiền tệ sẽ không nên lưu theo kiểu dữ liệu Floating-Point như
FLOAT
hayDOUBLE
. -
Các bạn có thể xem ví dụ dưới đây để hiểu rõ hơn sự khác nhau này:
-
Chúng ta tạo ra một bảng có tên là
t1
, trong đó bao gồm ba cột lài
,d1
vàd2
. Vớid1
vàd2
có kiểu dữ liệuDOUBLE
. -
Sau đó, chúng ta insert thêm 4 bản ghi cho bảng
t1
-
Rồi thực hiện câu lệnh
SELECT
để tính tổng hai cộtd1
vàd2
, với điều kiện sẽ chỉSELECT
ra dữ liệu nếu "tổng của cộtd1
" KHÁC "tổng của cộtd2
". -
Theo phép cộng thông thường, chúng ta có thể dễ dàng tính toán được là:
sum(d1) = 0-13.2+59.6+30.4 = 76.8 = sum(d2) = 0+0+46.4+30.4
-
Tuy nhiên, kết quả của MySQL cho thấy, 2 giá trị của
sum(d1)
vàsum(d2)
là khác nhau0.00000000000001
-
Cùng dữ liệu như vậy, nếu chúng ta lưu
d1
vàd2
là kiểuDECIMAL
thì kết quả sẽ đúng như mong đợi: 2 tổngsum(d1)
vàsum(d2)
có kết quả giống nhau (Kết quả trả về của câuSELECT
làEmpty set
, bởi vì nó đang kiểm tra điều kiện nếusum(d1) != sum(d2)
thì mớiSELECT
ra dữ liệu. Trường hợp nàysum(d1)
vàsum(d2)
bằng nhau nên kết quả trả về làEmpty set
.)
-
TÀI LIỆU THAM KHẢO
- Numeric Data Types - MySQL 8.0 Reference Manual: https://dev.mysql.com/doc/refman/8.0/en/numeric-types.html
- MySQL Data Types - w3schools: https://www.w3schools.com/mysql/mysql_datatypes.asp
- DOUBLE vs DECIMAL in MySQL - Stack Overflow: https://stackoverflow.com/questions/6831217/double-vs-decimal-in-mysql
Ngoài ra, các bạn cũng có thể follow page Facebook và channel Youtube này để cập nhật những thông tin thú vị về Lập trình nhé: Facebook Youtube