Trong SQL, mỗi cột trong bảng cơ sở dữ liệu được thiết kế để lưu trữ một loại dữ liệu cụ thể. Kiểu dữ liệu trong SQL là tập hợp các quy tắc xác định loại giá trị có thể được lưu trong một cột.
Ví dụ, nếu bạn có một cột dùng để lưu độ tuổi của người dùng, bạn nên đặt kiểu dữ liệu là INT
để đảm bảo chỉ có số nguyên được lưu trữ. Việc sử dụng đúng kiểu dữ liệu là yếu tố cốt lõi để duy trì tính toàn vẹn của dữ liệu, tối ưu dung lượng lưu trữ và đảm bảo hiệu năng cho cơ sở dữ liệu.
Kiểu dữ liệu trong SQL có thể được chia thành các nhóm chính sau:
- Kiểu số: bao gồm các kiểu như
INT
,TINYINT
,BIGINT
,FLOAT
,REAL
… - Kiểu ngày và thời gian: chẳng hạn như
DATE
,TIME
,DATETIME
… - Kiểu ký tự và chuỗi: gồm
CHAR
,VARCHAR
,TEXT
… - Kiểu chuỗi Unicode: như
NCHAR
,NVARCHAR
,NTEXT
… - Kiểu dữ liệu nhị phân: bao gồm
BINARY
,VARBINARY
… - Các kiểu đặc biệt khác: chẳng hạn
CLOB
,BLOB
,XML
,CURSOR
,TABLE
…
Dù nhiều kiểu dữ liệu đã được chuẩn hóa nhưng tên gọi và hành vi cụ thể có thể thay đổi giữa các hệ quản trị cơ sở dữ liệu như MySQL, PostgreSQL, và SQL Server. Trong hướng dẫn này, bạn sẽ nắm được những kiến thức cốt lõi để lựa chọn và sử dụng kiểu dữ liệu SQL phù hợp cho dự án của mình.
Lựa chọn kiểu dữ liệu SQL phù hợp
Việc lựa chọn kiểu dữ liệu không chỉ mang tính kỹ thuật thuần túy, mà còn đóng vai trò quan trọng trong vận hành thực tế của ứng dụng.
Hiệu quả lưu trữ: Tại sao phải dùng BIGINT
(chiếm 8 byte) cho một cột chỉ chứa các số từ 1 đến 10? Việc chọn kiểu dữ liệu nhỏ nhất nhưng vẫn đảm bảo bao phủ toàn bộ giá trị cần thiết sẽ tiết kiệm đáng kể không gian ổ đĩa, đặc biệt đối với bảng có kích thước lớn. Điều này liên quan trực tiếp đến kích thước kiểu dữ liệu trong SQL.
Hiệu suất: Kiểu dữ liệu nhỏ hơn giúp cơ sở dữ liệu đọc được nhiều dữ liệu hơn từ bộ nhớ hoặc ổ đĩa trong một lần thao tác, giúp truy vấn nhanh hơn. Các kiểu số được cấu hình đúng cách cũng được xử lý nhanh hơn đáng kể so với số lưu dưới dạng chuỗi.
Tính toàn vẹn dữ liệu: Kiểu dữ liệu áp đặt quy tắc cho dữ liệu được lưu. Một cột kiểu DATE
sẽ từ chối các giá trị không hợp lệ như 'Hello, World!'
, qua đó ngăn chặn dữ liệu không phù hợp ghi vào cơ sở dữ liệu. Đây chính là lớp kiểm soát đầu tiên giúp hạn chế lỗi phát sinh từ tầng ứng dụng. Để tìm hiểu thêm về tính toàn vẹn dữ liệu, bạn có thể tham khảo cơ chế sử dụng khóa chính trong SQL.
Khác biệt giữa các nhà cung cấp hệ quản trị cơ sở dữ liệu
Mặc dù các kiểu dữ liệu SQL được đề cập trong hướng dẫn này được sử dụng rộng rãi nhưng việc triển khai cụ thể có thể khác nhau giữa các hệ quản trị cơ sở dữ liệu. Trước khi hoàn thiện lược đồ cơ sở dữ liệu, bạn nên lưu ý các điểm khác biệt quan trọng sau:
1. Hỗ trợ không đồng nhất đối với các kiểu chuẩn
Không phải mọi hệ quản trị cơ sở dữ liệu đều hỗ trợ cùng một tập kiểu dữ liệu. Ví dụ, kiểu CLOB
(Character Large Object) phổ biến trong Oracle nhưng lại không được hỗ trợ trong MySQL, vốn sử dụng họ TEXT
để thay thế.
2. Kiểu dữ liệu độc quyền
Nhiều nhà cung cấp tự định nghĩa các kiểu dữ liệu chuyên biệt không tuân theo chuẩn ANSI SQL. Một ví dụ điển hình là Microsoft SQL Server với các kiểu tiện dụng như MONEY
và SMALLMONEY
để xử lý dữ liệu tiền tệ.
3. Giới hạn kích thước khác nhau
Kích thước tối đa cho một kiểu dữ liệu cụ thể — chẳng hạn như VARCHAR
— có thể khác nhau giữa các hệ quản trị.
Do sự khác biệt giữa các hệ quản trị cơ sở dữ liệu nên cách tốt nhất là luôn tham khảo tài liệu chính thức của hệ quản trị cơ sở dữ liệu mà bạn đang sử dụng. Việc này đảm bảo các kiểu dữ liệu bạn chọn được hỗ trợ đầy đủ và được cấu hình tối ưu cho từng tình huống cụ thể.
Kiểu dữ liệu số trong SQL
Kiểu dữ liệu số được dùng để lưu mọi loại dữ liệu dạng số. Chúng được chia thành nhiều nhóm, bao gồm kiểu chính xác (cho số nguyên và số thập phân) và kiểu xấp xỉ (cho tính toán khoa học, khi độ chính xác tuyệt đối không phải ưu tiên hàng đầu).
Dưới đây là bảng tổng hợp các kiểu dữ liệu số thông dụng trong SQL, kèm theo kích thước lưu trữ và phạm vi giá trị:
Kiểu dữ liệu | Kích thước lưu trữ | Phạm vi giá trị | Tình huống sử dụng phổ biến |
---|---|---|---|
TINYINT |
1 byte | 0 đến 255 (không dấu) hoặc -128 đến 127 (có dấu) | Số nguyên rất nhỏ. Dùng cho độ tuổi người, số lượng dưới 256. |
SMALLINT |
2 byte | -32.768 đến 32.767 | Số nguyên nhỏ. Thích hợp cho số trang sách, năm sản xuất. |
INT |
4 byte | -2.147.483.648 đến 2.147.483.647 | Số nguyên chuẩn. Lựa chọn phổ biến cho ID người dùng, số lượng sản phẩm. |
BIGINT |
8 byte | -9.223.372.036.854.775.808 đến 9.223.372.036.854.775.807 | Số nguyên rất lớn. Dùng cho ID giao dịch toàn cầu, dữ liệu khoa học. |
DECIMAL(p,s) |
Biến đổi | -10^38 + 1 đến 10^38 – 1 | Một số thập phân có giá trị chính xác với độ chính xác do người dùng xác định. Đây là kiểu dữ liệu đặc biệt quan trọng trong các ứng dụng tài chính và tiền tệ. Trong đó, p là tổng số chữ số, còn s là số chữ số sau dấu thập phân. |
NUMERIC(p,s) |
Biến đổi | -10^38 + 1 đến 10^38 – 1 | Tương đương với DECIMAL . Thường được dùng thay thế lẫn nhau. |
FLOAT(n) |
4 hoặc 8 byte | -1.79E+308 đến 1.79E+308 | Số thực xấp xỉ. Dùng cho tính toán khoa học, chấp nhận mất một phần độ chính xác. |
REAL |
4 byte | -3.40E+38 đến 3.40E+38 | Số thực xấp xỉ đơn độ chính xác. Nhẹ hơn và kém chính xác hơn FLOAT . |
Kiểu dữ liệu ngày và giờ trong SQL
Lưu trữ chính xác ngày giờ là điều then chốt đối với việc ghi nhật ký, lập lịch và theo dõi sự kiện. Sự khác biệt cốt lõi giữa các kiểu nằm ở phạm vi sử dụng:
- Dùng
DATE
cho các giá trị như ngày sinh, khi thời gian trong ngày không quan trọng. - Dùng
DATETIME
hoặcTIMESTAMP
khi cần ghi lại chính xác thời điểm xảy ra một sự kiện, như lúc người dùng đăng nhập hoặc đơn hàng được tạo.
Kiểu dữ liệu | Mô tả |
---|---|
DATE |
Lưu ngày dưới định dạng YYYY-MM-DD |
TIME |
Lưu giờ dưới định dạng HH:MI:SS |
DATETIME |
Lưu cả ngày và giờ theo định dạng YYYY-MM-DD HH:MI:SS |
TIMESTAMP |
Lưu số giây đã trôi qua kể từ Unix epoch ('1970-01-01 00:00:00' UTC ) |
YEAR |
Lưu năm dưới dạng 2 hoặc 4 chữ số. Dải giá trị từ 1901 đến 2155 với định dạng 4 chữ số; từ 70 đến 69 với định dạng 2 chữ số, tương ứng với năm 1970 đến 2069 |
Kiểu dữ liệu chuỗi và chuỗi Unicode trong SQL
Kiểu chuỗi dùng để lưu tất cả dạng văn bản, từ ký tự đơn cho đến toàn bộ tài liệu. Quyết định phổ biến nhất là lựa chọn giữa kiểu độ dài cố định (chiếm không gian như nhau bất kể nội dung) và kiểu độ dài biến đổi (thích nghi theo độ dài dữ liệu). Một yếu tố quan trọng khác là việc có cần hỗ trợ ký tự quốc tế bằng Unicode hay không.
Bảng sau cung cấp cái nhìn tổng quan về các kiểu dữ liệu ký tự và chuỗi phổ biến nhất.
Kiểu dữ liệu | Mô tả và mục đích | Hỗ trợ Unicode | Kích thước tối đa (SQL Server) | Tình huống sử dụng phổ biến |
---|---|---|---|---|
CHAR(n) |
Chuỗi cố định độ dài. Tự động thêm khoảng trắng cho đủ độ dài n. | Không | 8.000 ký tự | Mã bang 2 ký tự (CA ), mã sản phẩm (SKU123 ), cờ Y/N. Dùng khi dữ liệu luôn có độ dài cố định. |
VARCHAR(n) |
Chuỗi biến độ dài (tối đa n ), chỉ dùng bộ nhớ theo nội dung thực. |
Không | 8.000 ký tự (tối đa 65.535 byte trong MySQL) | Tên người dùng, email, tiêu đề… Kiểu chuỗi phổ biến và linh hoạt nhất cho văn bản không Unicode. |
TEXT |
Chuỗi biến độ dài để lưu trữ khối văn bản rất lớn. | Không | 2 GB | Mô tả sản phẩm dài, nội dung bài viết, bình luận người dùng. |
NCHAR(n) |
Tập ký tự quốc gia**.** Chuỗi Unicode cố định độ dài. Cần thiết cho dữ liệu đa ngôn ngữ có độ dài nhất quán. | Có | 4.000 ký tự | Lưu mã định danh hoặc mã trong nhiều ngôn ngữ với độ dài cố định. |
NVARCHAR(n) |
Tập ký tự quốc gia. Chuỗi Unicode biến độ dài. Lựa chọn chuẩn để lưu văn bản đa ngôn ngữ. | Có | 4.000 ký tự (hoặc NVARCHAR(MAX ) tới 2GB) |
Lưu tên người, bình luận, văn bản từ người dùng toàn cầu. |
NTEXT |
Tập ký tự quốc gia. Một kiểu dữ liệu cũ dùng để lưu trữ các khối văn bản Unicode có kích thước lớn. | Có | 2 GB | Trước đây dùng để lưu tài liệu lớn đa ngôn ngữ. Ngày nay SQL Server hiện đại ưu tiên NVARCHAR(MAX ). |
Lưu ý: MySQL xử lý Unicode theo cách khác biệt. Hệ quản trị này không sử dụng các kiểu dữ liệu như NCHAR
, NVARCHAR
hay NTEXT
. Thay vào đó, bạn sử dụng các kiểu tiêu chuẩn như VARCHAR
hoặc TEXT
, và chỉ định bộ ký tự cho cột là một bộ tương thích với Unicode, chẳng hạn utf8mb4
.
Ví dụ:
*username VARCHAR(100) CHARACTER SET utf8mb4*
Kiểu dữ liệu nhị phân trong SQL
Kiểu nhị phân dùng để lưu dữ liệu dạng thô (không đọc được bằng mắt người), như tập tin. Đây là lựa chọn bắt buộc khi bạn cần lưu hình ảnh, âm thanh, mã đã biên dịch… trực tiếp trong cơ sở dữ liệu.
Kiểu dữ liệu | Mô tả | Tình huống sử dụng phổ biến | Kích thước tối đa |
---|---|---|---|
BINARY(n) |
Kiểu nhị phân cố định độ dài n byte. Nếu dữ liệu ngắn hơn n , tự động thêm byte 0. |
Lưu dữ liệu luôn có kích thước cố định, như mã băm (hash) MD5 (luôn 16 byte) hoặc mã định danh có độ dài cố định. | Tối đa 8.000 byte (SQL Server); 255 byte (MySQL) |
VARBINARY(n) |
Kiểu nhị phân biến độ dài với giới hạn n byte. Không đệm dữ liệu, tiết kiệm không gian. |
Lưu trữ dữ liệu nhị phân nhỏ, có kích thước biến đổi, chẳng hạn như hình thu nhỏ do người dùng tải lên, mã QR, hoặc các đối tượng khác có kích thước tối đa đã biết trước. | Tối đa 8.000 byte (SQL Server); 65.535 byte (MySQL) |
BLOB |
Đối tượng nhị phân lớn (Binary Large Object) là kiểu dữ liệu dùng để lưu trữ dữ liệu nhị phân có kích thước rất lớn. Trong MySQL, đây là một họ các kiểu dữ liệu gồm TINYBLOB , BLOB , MEDIUMBLOB và LONGBLOB , đáp ứng các yêu cầu kích thước khác nhau. |
Lưu trực tiếp tập tin như hình ảnh, âm thanh, tài liệu PDF, đối tượng lập trình được tuần tự hóa… | Tối đa 4 GB (LONGBLOB trong MySQL) |
IMAGE (Legacy) |
Kiểu dữ liệu cũ trong các phiên bản SQL Server trước đây, tương đương với BLOB . |
Trước đây được sử dụng để lưu trữ hình ảnh**.** Trong SQL Server hiện đại, VARBINARY(MAX) là lựa chọn thay thế được khuyến nghị nhờ tính linh hoạt cao hơn. |
2 GB |
Lưu ý: Mặc dù việc lưu trữ hình ảnh nhỏ hoặc tập tin trực tiếp vào trường BLOB
rất tiện lợi nhưng đối với các ứng dụng lớn và có lưu lượng cao, tốt hơn hết bạn nên lưu tập tin trên hệ thống tập tin riêng hoặc dịch vụ lưu trữ đối tượng (như DigitalOcean Spaces), sau đó chỉ lưu đường dẫn hoặc URL trong cơ sở dữ liệu.
Kiểu dữ liệu đặc biệt trong SQL
SQL hiện nay hỗ trợ nhiều kiểu dữ liệu chuyên biệt phục vụ cho các cấu trúc hiện đại như JSON, dữ liệu địa lý, hoặc giá trị logic.
Kiểu dữ liệu | Mô tả | Tình huống sử dụng phổ biến | Kích thước tối đa |
---|---|---|---|
JSON |
Lưu chuỗi văn bản theo định dạng JavaScript Object Notation. Nhiều hệ quản trị hỗ trợ hàm và toán tử để truy vấn dạng dữ liệu này. | Lưu cấu hình ứng dụng, nhật ký, dữ liệu từ API bên thứ ba. Phù hợp cho dữ liệu bán cấu trúc không cần schema cứng. | Biến đổi, thường từ 1 đến 4 GB (giới hạn bởi kiểu TEXT/BLOB) |
XML |
Lưu dữ liệu theo định dạng eXtensible Markup Language. Có thể kèm theo phương thức xác thực bằng schema XML. | Lưu tập tin cấu hình, dữ liệu từ hệ thống doanh nghiệp cũ (ví dụ như SOAP APIs), hoặc tài liệu có cấu trúc khác. | 2 GB (SQL Server) |
CLOB |
Đối tượng ký tự lớn. Thuật ngữ chuẩn SQL dùng để lưu văn bản có kích thước đặc biệt lớn. | Lưu trữ toàn bộ tệp văn bản hoặc các tài liệu dài như sách. (Từ khóa này phổ biến trong Oracle; MySQL sử dụng họ TEXT , còn SQL Server dùng VARCHAR(MAX) .) |
Biến đổi, thường từ 2 GB trở lên |
BOOLEAN |
Lưu giá trị logic TRUE hoặc FALSE . Một số hệ còn hỗ trợ trạng thái “không xác định” (NULL ). |
Cờ trạng thái như is_active , has_subscribed , is_verified … (Lưu ý: MySQL dùng TINYINT(1) thay thế) |
1 byte |
UUID |
Định danh duy nhất toàn cục. Một số 128 bit dùng để nhận diện dữ liệu trên nhiều hệ thống. | Tạo khóa chính duy nhất, đặc biệt là trong các hệ cơ sở dữ liệu phân tán, nơi các số nguyên tự động tăng từ các máy chủ khác nhau có thể bị trùng lặp. | 16 byte (128 bit) |
Kiểu dữ liệu SQL trong các hệ quản trị cơ sở dữ liệu khác nhau
Mặc dù các kiểu dữ liệu cơ bản như INT
và VARCHAR
được hầu hết hệ quản trị cơ sở dữ liệu hỗ trợ nhưng mỗi hệ thống lớn đều có những biến thể riêng, bổ sung kiểu dữ liệu độc quyền hoặc thay đổi hành vi của kiểu chuẩn. Hiểu rõ những khác biệt này là điều then chốt để viết mã SQL vừa hiệu quả vừa dễ chuyển đổi.
Kiểu dữ liệu trong MySQL
MySQL nổi tiếng với tính thân thiện và cung cấp nhiều tính năng tiện dụng, không hoàn toàn tuân thủ tiêu chuẩn.
ENUM
: Một tính năng rất phổ biến của MySQL, cho phép chúng ta tạo một đối tượng chuỗi mà giá trị của cột bắt buộc phải được chọn từ một danh sách xác định trước. Kiểu dữ liệu này rất hiệu quả khi các giá trị được lưu nội bộ dưới dạng số nguyên nhỏ. Tuy nhiên, nếu sau này bạn muốn thêm giá trị mới vào danh sách thì có thể làm chậm hệ thống và gây khóa bảng, đặc biệt là đối với các bảng có kích thước lớn.SET
: Tương tựENUM
nhưng cho phép một cột chứa nhiều giá trị trong danh sách định sẵn.- Thuộc tính
UNSIGNED
: Đây không phải là một kiểu dữ liệu, mà là một thuộc tính rất quan trọng đối với các kiểu số. Khi khai báo một số làUNSIGNED
, bạn ngăn không cho nó lưu giá trị âm, đồng thời tăng gấp đôi phạm vi giá trị dương có thể lưu trữ.
Ví dụ, một INT UNSIGNED
có phạm vi từ 0
đến 4.294.967.295
, nó thường được sử dụng làm khóa chính.
YEAR
: Kiểu 1 byte để lưu năm. Có thể khai báo làYEAR(4)
để lưu 4 chữ số, hoặcYEAR(2)
(định dạng cũ), hiện không còn được khuyến khích sử dụng.
Kiểu dữ liệu trong PostgreSQL
PostgreSQL (hay Postgres) nổi tiếng nhờ tính tuân thủ chuẩn cao và hỗ trợ kiểu dữ liệu phong phú, phức tạp.
ARRAY
: Cho phép một cột lưu trữ mảng giá trị. Giúp giản lược lược đồ trong các trường hợp thay vì tạo bảng liên kết.JSONB
vsJSON
: Có hai kiểu để lưu JSON trong PostgreSQL.JSON
lưu dạng văn bản gốc, cònJSONB
lưu dưới dạng nhị phân đã phân tích cú pháp.JSONB
truy vấn và hỗ trợ lập chỉ mục nhanh hơn, nên đây là lựa chọn ưu tiên của hầu hết các ứng dụng.UUID
: Kiểu gốc để lưu UUID 128 bit. Được ưu tiên thaySERIAL
làm khóa chính trong hệ phân tán nhằm tránh xung đột ID.- Kiểu địa chỉ mạng: PostgreSQL hỗ trợ các kiểu dữ liệu gốc như
INET
vàCIDR
để lưu trữ và kiểm tra tính hợp lệ của địa chỉ IPv4 và IPv6 bao gồm cả địa chỉ máy chủ và địa chỉ mạng.
Kiểu dữ liệu trong SQL Server
SQL Server của Microsoft cung cấp tập kiểu mạnh mẽ với trọng tâm là hệ sinh thái tích hợp.
MONEY
/SMALLMONEY
: Các kiểu dữ liệu này được tối ưu cho tiền tệ, lưu giá trị với 4 chữ số thập phân cố định. Tuy nhiên, nhiều lập trình viên vẫn thích kiểu tiêu chuẩnDECIMAL
hơn để kiểm soát chính xác hơn.DATETIME2
: Đây là phiên bản hiện đại và được khuyến nghị thay cho kiểuDATETIME
cũ. Nó hỗ trợ phạm vi ngày rộng hơn (từ năm 0001 đến 9999), cho phép người dùng xác định độ chính xác phần thập phân của giây, và tuân thủ tốt hơn chuẩn ANSI SQL.UNIQUEIDENTIFIER
: Đây là kiểu dữ liệu gốc của SQL Server để lưu UUID. Thường được sử dụng cùng với hàmNEWID()
để tạo khóa chính duy nhất.VARCHAR(MAX)
/NVARCHAR(MAX)
: Những kiểu này thay thế choTEXT
vàNTEXT
cũ. Chúng cung cấp khả năng lưu trữ lớn như một đối tượng (tối đa 2 GB) trong khi vẫn giữ được nhiều đặc tính thuận tiện củaVARCHAR
thông thường.
Kiểu dữ liệu trong Oracle SQL
Cơ sở dữ liệu Oracle có lịch sử lâu đời với nhiều cách triển khai kiểu dữ liệu đặc thù.
VARCHAR2(n)
: Đây là kiểu chuỗi có độ dài biến đổi chính trong Oracle. Mặc dù Oracle cũng cung cấp kiểuVARCHAR
, nhưng việc sử dụng kiểu này không được khuyến khích. Thay vào đó, bạn nên dùngVARCHAR2
để đảm bảo hành vi nhất quán khi xử lý dữ liệu dạng chuỗi.NUMBER
: Kiểu số cực kỳ linh hoạt và toàn diện. Có thể khai báo dưới dạngNUMBER(p,s)
để hoạt động như số thập phân cố định (giốngDECIMAL
),NUMBER(p)
như một số nguyên, hoặc đơn giản làNUMBER
để lưu số thực (dạng dấu chấm động).DATE
: Đây là một điểm thường gây nhầm lẫn. Không giống như kiểuDATE
trong chuẩn SQL, chỉ lưu ngày, kiểuDATE
trong Oracle luôn bao gồm cả ngày và giờ, về chức năng tương đương với kiểuDATETIME
trong các hệ quản trị khác.CLOB
/BLOB
/NCLOB
: Oracle định nghĩa rõ ràng các kiểu dữ liệu “Large Object” (LOB) để lưu trữ khối lượng lớn dữ liệu:BLOB
: Dữ liệu nhị phân.CLOB
: Văn bản ký tự.NCLOB
: Văn bản Unicode.
Ép kiểu và chuyển đổi kiểu dữ liệu trong SQL
Ép kiểu, hay chuyển đổi kiểu dữ liệu, là quá trình chuyển giá trị từ kiểu này sang kiểu khác. Thao tác này cần thiết khi cần so sánh dữ liệu khác kiểu, định dạng đầu ra hoặc thực hiện phép tính trên dữ liệu dạng văn bản.
Có hai dạng chuyển đổi: ngầm định (tự động) và tường minh (thủ công).
- Chuyển đổi ngầm định: Đây là khi cơ sở dữ liệu tự động chuyển đổi kiểu dữ liệu cho bạn ở phía sau.
Ví dụ, trong truy vấn WHERE my_integer_column = '123'
, cơ sở dữ liệu sẽ ngầm định chuyển chuỗi '123'
thành số nguyên để thực hiện so sánh. Tuy thuận tiện, nhưng việc chuyển đổi ngầm định thường không được khuyến khích, vì có thể gây ra kết quả sai lệch hoặc làm giảm hiệu năng truy vấn.
- Chuyển đổi tường minh: Đây là khi bạn chủ động sử dụng một hàm để chuyển đổi kiểu dữ liệu. Đây là cách được khuyến nghị vì giúp mã nguồn dễ hiểu, rõ ràng và đảm bảo quá trình chuyển đổi diễn ra theo cách nhất quán và có thể kiểm soát. Hai hàm chính để làm điều này là
CAST()
vàCONVERT()
:
- CAST(): Hàm
CAST()
là chuẩn ANSI SQL, có nghĩa là nó có sẵn trong hầu hết các hệ quản trị cơ sở dữ liệu, bao gồm MySQL, PostgreSQL và SQL Server. Điều này khiến nó trở thành hàm chuyển đổi phổ biến và có tính di động cao nhất. Cú pháp là:
CAST(biểu_thức AS kiểu_mục_tiêu)
- CONVERT(): Chủ yếu dùng trong SQL Server, linh hoạt hơn CAST, đặc biệt khi định dạng ngày giờ. Cú pháp:
CONVERT(kiểu_mục_tiêu, biểu_thức, [mã_định_dạng])
Tham số style_code
là một số dùng để xác định định dạng đầu ra khi chuyển đổi ngày/giờ hoặc số thành chuỗi.
Nguyên tắc tối ưu hóa khi lựa chọn kiểu dữ liệu
Trong thiết kế cơ sở dữ liệu, “càng nhỏ càng tốt”. Mặc dù chi phí lưu trữ hiện nay không còn đắt đỏ nhưng kích thước kiểu dữ liệu vẫn ảnh hưởng trực tiếp đến tốc độ truy vấn, mức tiêu thụ bộ nhớ và hiệu năng tổng thể của ứng dụng.
Dưới đây là một số nguyên tắc lựa chọn kích thước kiểu dữ liệu hiệu quả nhất:
- Dùng kiểu nhỏ nhất có thể mà vẫn đủ (Quy tắc Goldilocks)Đây là nguyên tắc cơ bản nhất: Đừng mặc định dùng
INT
nếuTINYINT
là đủ.Đối với kiểu số nguyên:
- Tuổi người dùng: Tuổi của một người gần như không bao giờ vượt quá 200. Vì vậy,
TINYINT UNSIGNED
(có phạm vi từ 0 đến 255) là lựa chọn lý tưởng và chỉ sử dụng 1 byte. Việc dùngINT
(4 byte) trong trường hợp này là lãng phí. - Mã người dùng (User ID):
INT
(với giới hạn lên tới 2,1 tỷ) là đủ cho đa số hệ thống. Không nên mặc định dùngBIGINT
(lên tới 9 triệu tỷ) vìBIGINT
chiếm gấp đôi dung lượng (8 byte) so vớiINT
, điều này sẽ trở nên tốn kém khi áp dụng trên hàng triệu dòng dữ liệu và các khóa ngoại liên quan.
Đối với chuỗi ký tự:
- Địa chỉ email: Dù địa chỉ email có thể dài nhưng chúng có giới hạn rõ ràng.
VARCHAR(255)
là một lựa chọn an toàn và tiêu chuẩn. Không cần thiết sử dụngVARCHAR(4000)
. - Cờ trạng thái (status flags): Với các trạng thái như
active
,pending
, hoặcdeleted
, không nên dùngVARCHAR(20)
. Trong MySQL, bạn nên dùngENUM
; hoặc với các hệ quản trị khác, dùng khóa ngoại trỏ đến bảng tra cứu vớiTINYINT
làm khóa chính.
- Tuổi người dùng: Tuổi của một người gần như không bao giờ vượt quá 200. Vì vậy,
- Hiểu rõ dữ liệu của bạnTrước khi chọn kiểu, đặt câu hỏi: Giá trị có thể âm không? Nếu không, dùng UNSIGNED. Có phần thập phân không? Nếu có, dùng DECIMAL. Mã sản phẩm tối đa dài bao nhiêu? Ví dụ: mã Zip Code ở Mỹ có thể có số 0 đầu (07660). Nếu lưu bằng INT sẽ mất số 0. Nên dùng CHAR(5) để bảo toàn định dạng.
Trước khi chọn kiểu dữ liệu, bạn cần hiểu rõ miền giá trị của dữ liệu. Sau đó, tự đặt các câu hỏi như:
- Giá trị này có bao giờ âm không? Nếu không, hãy cân nhắc sử dụng thuộc tính
UNSIGNED
(đối với MySQL). - Dữ liệu có phần thập phân không? Nếu có, bạn cần kiểu
DECIMAL
. - Độ dài tối đa tuyệt đối của mã sản phẩm (SKU) là bao nhiêu?
Ví dụ: mã bưu chính (ZIP code) của Hoa Kỳ. Nhiều người có xu hướng chọn kiểu
INT
để lưu mã ZIP, nhưng đây là một sai lầm phổ biến. Mã ZIP của Mỹ có thể có số 0 đứng đầu (ví dụ:07660
), và khi lưu dưới dạng số, các số 0 đầu sẽ bị mất. Cách đúng là dùngCHAR(5)
để bảo toàn được định dạng gốc của mã ZIP và sử dụng không gian cố định, dễ đoán. - Giá trị này có bao giờ âm không? Nếu không, hãy cân nhắc sử dụng thuộc tính
- Kế hoạch dự phòng hợp lý cho tương lai, tránh lạm dụng
Lập kế hoạch mở rộng là điều cần thiết nhưng đừng thiết kế quá mức.
- Dự phòng hợp lý:Chọn
INT
thay vìSMALLINT
cho khóa chính thường là một quyết định dài hạn thông minh. Sự khác biệt về dung lượng chỉ là 2 byte nhưng cung cấp dư địa lớn hơn nhiều để mở rộng trong tương lai. - Thiết kế quá mức không cần thiết:Việc mặc định dùng
NVARCHAR
cho tất cả các trường văn bản với lý do “phòng khi sau này cần hỗ trợ Unicode” là không hợp lý nếu ứng dụng của bạn chỉ hướng đến nội dung tiếng Anh.NVARCHAR
sử dụng gấp đôi dung lượng so vớiVARCHAR
. Hãy đưa ra quyết định dựa trên yêu cầu thực tế.
- Hiểu rõ sự đánh đổi giữa CHAR và VARCHAR
CHAR(n)
:Chỉ nên dùng khi dữ liệu luôn có độ dài cố định. Ví dụ:- Mã quốc gia gồm 2 ký tự:
CHAR(2)
- UUID lưu dạng chuỗi:
CHAR(36)
- Mã quốc gia gồm 2 ký tự:
Nếu dữ liệu ngắn, CHAR
sẽ tự động thêm dấu cách cho đủ chiều dài, điều này có thể gây lãng phí.
VARCHAR(n)
:Đây là lựa chọn phù hợp cho hầu hết dữ liệu văn bản. Chỉ lưu đúng số ký tự thực tế cộng thêm 1 hoặc 2 byte để lưu độ dài, rất hiệu quả khi làm việc với dữ liệu có độ dài biến đổi.
Câu hỏi thường gặp
1. Các nhóm chính của kiểu dữ liệu trong SQL là gì?
Kiểu dữ liệu trong SQL được phân chia thành nhiều nhóm logic dựa trên loại dữ liệu mà chúng lưu trữ. Các nhóm chính bao gồm:
- Kiểu số (Numeric Types): Dành cho dữ liệu thuần toán học. Nhóm này bao gồm các kiểu số nguyên cho số nguyên (như
INT
,BIGINT
) và các kiểu số thực hoặc thập phân cho số có phần lẻ (nhưDECIMAL
,FLOAT
). Bạn sẽ dùng chúng cho các trường như ID, số lượng, giá cả,… - Kiểu ký tự/chuỗi (Character/String Types): Dùng để lưu văn bản. Bao gồm kiểu độ dài cố định (
CHAR
) cho chuỗi có độ dài xác định trước (như mã bang), và kiểu độ dài thay đổi (VARCHAR
) cho chuỗi có độ dài linh hoạt như tên, tiêu đề. Với văn bản dài như nhận xét hoặc bài viết, bạn có thể dùng kiểu đối tượng lớn nhưTEXT
. - Kiểu ngày giờ (Date and Time Types): Lưu trữ thông tin thời gian, trả lời cho câu hỏi khi nào sự kiện xảy ra. Bao gồm
DATE
(chỉ ngày),TIME
(chỉ thời gian), hoặc kết hợp cả hai nhưDATETIME
,TIMESTAMP
. - Kiểu nhị phân (Binary Types): Lưu dữ liệu nhị phân thô, tức là chuỗi byte không thể đọc được bằng mắt thường, dùng để lưu file, ảnh hoặc đối tượng nhị phân. Các kiểu phổ biến gồm:
BINARY
,VARBINARY
,BLOB
. - Kiểu đặc biệt/khác (Miscellaneous/Specialized Types): Là các kiểu hiện đại được bổ sung thêm theo thời gian. Bao gồm
BOOLEAN
cho trạng thái đúng/sai,JSON
cho dữ liệu từ API web,XML
cho tài liệu có cấu trúc, và kiểu không gian (spatial) cho dữ liệu địa lý.
2. Sự khác biệt giữa VARCHAR và TEXT trong SQL là gì?
Khác biệt giữa VARCHAR
và TEXT
nằm ở ba khía cạnh chính: độ dài xác định, cách lưu trữ và mục đích sử dụng.
- VARCHAR (Chuỗi có độ dài thay đổi): Bạn phải chỉ định độ dài tối đa (ví dụ:
VARCHAR(255)
). Cơ sở dữ liệu sẽ kiểm tra giới hạn này khi chèn dữ liệu. Phù hợp với văn bản có độ dài dự kiến, như tên người dùng, email, tên thành phố. Dữ liệuVARCHAR
thường được lưu cùng với các cột khác trong cùng hàng, giúp truy xuất nhanh. - TEXT: Không cần chỉ định độ dài tối đa. Dùng cho văn bản dài, không xác định độ dài, có thể lên đến hàng MB hoặc GB. Vì kích thước lớn, dữ liệu
TEXT
thường được lưu tách biệt khỏi phần còn lại của hàng, dẫn đến độ trễ nhỏ khi truy xuất so vớiVARCHAR
. DùngTEXT
cho bài blog, mô tả dài hoặc nội dung do người dùng tạo.
Tóm lại:
- Dùng
VARCHAR
khi bạn biết giới hạn và cần tốc độ truy cập cao. - Dùng
TEXT
khi dữ liệu quá dài hoặc không xác định trước độ dài.
3. Kiểu dữ liệu SQL khác nhau thế nào giữa MySQL và PostgreSQL?
Dù cả hai đều hỗ trợ các kiểu chuẩn SQL, mỗi hệ quản trị lại có những điểm riêng biệt:
PostgreSQL:
Được đánh giá cao nhờ khả năng hỗ trợ kiểu dữ liệu phong phú và tuân thủ chuẩn SQL. Nó cung cấp các lựa chọn hữu ích không có trong MySQL như:
ARRAY
: Một cột có thể lưu danh sách giá trị (mảng) như mảng số nguyên, chuỗi,…UUID
: Kiểu gốc để lưu mã nhận dạng toàn cục 128-bit, lý tưởng cho khóa chính trong hệ phân tán.JSONB
: Dạng nhị phân có chỉ mục của JSON, hiệu quả hơn khi truy vấn và lưu trữ dữ liệu phức tạp.BOOLEAN
: Kiểu gốc chỉ nhậntrue
hoặcfalse
.
MySQL:
Hướng đến sự tiện lợi, dễ dùng, với một số kiểu phổ biến:
ENUM
: Cho phép cột chỉ nhận các giá trị trong danh sách định sẵn, ví dụ:ENUM('active', 'inactive')
. Lưu dưới dạng số nhỏ bên trong nên rất hiệu quả.SET
: Tương tựENUM
, nhưng cho phép lưu nhiều giá trị cùng lúc.UNSIGNED
: Cho phép kiểu số không âm, giúp tăng gấp đôi dải số dương. Ví dụ:TINYINT UNSIGNED
từ 0 đến 255, thay vì -128 đến 127.
4. Kích thước mặc định của INT trong SQL là bao nhiêu?
Trong hầu hết các hệ quản trị cơ sở dữ liệu hiện đại như MySQL, PostgreSQL, SQL Server, kiểu INT
hay INTEGER
có kích thước 4 byte (32-bit).
- Một byte gồm 8 bit → 4 byte = 32 bit → biểu diễn được 2³² = 4.294.967.296 giá trị khác nhau.
- Với kiểu
INT
có dấu thông thường, phạm vi giá trị được chia đều giữa số âm và số dương, từ -2.147.483.648 đến 2.147.483.647. Đây là thiết lập mặc định. - Với
UNSIGNED INT
(nếu hệ quản trị hỗ trợ, như MySQL), dải giá trị từ 0 đến 4.294.967.295, tức là tận dụng toàn bộ 32 bit cho giá trị dương.
Kết luận
Bài viết đã trình bày toàn diện về kiểu dữ liệu trong SQL, nhấn mạnh vai trò quan trọng của chúng đối với hiệu năng, tính toàn vẹn và lưu trữ. Chúng ta đã đi qua từng nhóm kiểu dữ liệu, từ số, chuỗi, đến kiểu đặc biệt như JSON và UUID, đồng thời phân tích sự khác biệt quan trọng giữa các hệ quản trị phổ biến như MySQL, PostgreSQL, SQL Server và Oracle. Cuối cùng là các kỹ thuật nâng cao như ép kiểu và tối ưu kích thước lưu trữ.
Việc hiểu rõ kiểu dữ liệu không chỉ giúp tối ưu hiệu suất mà còn đưa bạn tiến gần hơn đến việc làm chủ SQL một cách toàn diện.