Câu 1Trong console của khóa học này, bạn INSERT chuỗi '123' vào cột khai báo INTEGER. Phát biểu nào đúng?
Chuỗi, số, kiểu boolean và chuyển đổi kiểu ngầm định
Dùng bảng typed_demo để thấy kiểu khai báo khác lớp lưu trữ ra sao, xem '10' và 123 chuyển qua lại với typeof(), tìm hiểu boolean được biểu diễn bằng 0 / 1, và so sánh tất cả với các kiểu nghiêm ngặt CHAR / VARCHAR / INT / DECIMAL của MySQL bằng cách chạy truy vấn thật.
Dữ liệu sẽ dùng — bảng typed_demo
Khi bạn tạo một cột, bạn khai báo một kiểu như INTEGER / TEXT / REAL, và kiểu đó quyết định cách cột xử lý các giá trị mà nó chứa.
Trong bài này bạn sẽ đi qua cách chuỗi, số và boolean được lưu trữ và so sánh trong SQL, và cách console của khóa học này xử lý kiểu (được gọi là type affinity trong tài liệu SQLite) khác với các kiểu nghiêm ngặt trong MySQL ra sao.
Kiểu khai báo so với lớp lưu trữ — mỗi giá trị mang kiểu riêng
Kiểu mà một giá trị thực sự có lúc chạy được gọi là lớp lưu trữ (storage class), và có năm loại: NULL / INTEGER (số nguyên) / REAL (số thập phân) / TEXT (chuỗi) / BLOB (nhị phân).
Bạn có thể kiểm tra lớp lưu trữ hiện tại của một giá trị với hàm typeof(giá_trị).
Nếu bạn đưa một chuỗi trông giống số vào cột khai báo TEXT, chính sách của cột là "xem đây là text", nên nó vẫn là chuỗi.
Nhưng nếu bạn đưa một chuỗi trông giống số như '123' vào cột khai báo INTEGER, chính sách của cột sẽ áp dụng và chuyển nó thành số nguyên 123 trước khi lưu.
'123' vào cột INTEGER trở thành số nguyên, trong khi '10' vào cột TEXT vẫn là chuỗi. Kiểu thực tế của mỗi giá trị luôn có thể kiểm tra bằng typeof().-- Ví dụ độc lập minh họa "kiểu khai báo của cột quyết định kiểu được lưu"
-- Chuỗi trông giống số trong cột INTEGER sẽ được chuyển thành số nguyên
CREATE TABLE IF NOT EXISTS aff_probe(num INTEGER, txt TEXT);
INSERT OR IGNORE INTO aff_probe VALUES ('123','123'), ('hello','hello');
-- Dùng typeof để kiểm tra lớp lưu trữ thực tế
SELECT num, typeof(num) AS num_class,
txt, typeof(txt) AS txt_class
FROM aff_probe;
-- Cột num: '123' thành integer, 'hello' không chuyển được nên vẫn là text
-- Cột txt: cả hai đều là text
Chuỗi và số chuyển qua lại — '123' và 123
Khi cần một số, chuỗi sẽ được chuyển thành số tự động; khi cần một chuỗi, số sẽ được chuyển thành chuỗi.
Ví dụ, '123' + 0 chuyển chuỗi '123' thành số 123 và trả về 123, nên các chuỗi trông giống số có thể đưa thẳng vào phép tính.
Ngược lại, 123 || '' (|| là phép nối chuỗi) biến số thành chuỗi.
Các toán tử so sánh hoạt động theo cách tương tự: nếu một bên là cột INTEGER, bên kia được căn chỉnh thành số; nếu một bên là cột TEXT, bên kia được căn chỉnh thành chuỗi.
Nhưng với hai literal thô như '1' = 1 không có cột nào để đặt chính sách, nên các giá trị giữ nguyên kiểu khác nhau và kết quả là 0 (không khớp).
-- Quan sát chuyển đổi chuỗi <-> số (ví dụ chỉ đọc)
SELECT '123' + 0 AS str_to_num, -- chuỗi thành số 123
'abc' + 0 AS not_a_num, -- không chuyển được, thành 0
123 || '' AS num_to_str, -- số thành chuỗi '123'
typeof('123' + 0) AS class_after_add,
'1' = 1 AS literal_cmp, -- literal thô: 0 (không khớp)
7 / 2 AS int_div, -- integer / integer = integer 3
7.0 / 2 AS real_div; -- có số thập phân thì cho 3.5
Boolean — TRUE / FALSE được lưu dưới dạng 1 / 0
SQL không có kiểu boolean độc lập — các giá trị chân lý được biểu diễn bằng số nguyên 1 (true) và 0 (false).
Các biểu thức so sánh như 1 = 1 hoặc 3 > 2 trả về 1 cho true và 0 cho false.
Ở bất cứ chỗ nào bạn có thể viết điều kiện, như CASE WHEN cột THEN ..., bất kỳ giá trị nào khác 0 (thường là 1) được xem là true, còn 0 được xem là false.
NULL là trạng thái thứ ba không phải true cũng không phải false ("không xác định"), và trong điều kiện WHERE hoặc CASE nó hành xử như false theo nghĩa dòng đó "không được chọn".
-- Biểu thức so sánh trả về 1 / 0 (ví dụ chỉ đọc)
SELECT (1 = 1) AS is_true, -- 1
(1 = 2) AS is_false, -- 0
(3 > 2) AS gt, -- 1
TRUE AS true_kw, -- giống 1
FALSE AS false_kw; -- giống 0
-- Dùng cột flag trực tiếp làm điều kiện
SELECT a, flag,
CASE WHEN flag THEN 'enabled' ELSE 'disabled' END AS state
FROM typed_demo;
So sánh với các kiểu nghiêm ngặt của MySQL
Những gì bạn vừa thấy là chuyển đổi kiểu ngầm định — các giá trị được định hình lại linh hoạt dựa theo ngữ cảnh.
Ngược lại, MySQL và Oracle có kiểu nghiêm ngặt: khi bạn khai báo CHAR(10) / VARCHAR(255) / TEXT cho chuỗi hoặc INT / DECIMAL(10,2) cho số, chỉ giá trị của kiểu đó mới được nạp vào, và độ dài và độ chính xác được áp đặt đúng như khai báo.
Một số thường không lọt vào cột chuỗi qua chuyển đổi ngầm, và các giá trị vượt quá độ dài khai báo sẽ báo lỗi hoặc bị cắt bớt.
Đoạn code bên dưới là cách MySQL khai báo kiểu.
Console của khóa học này không kiểm tra độ dài theo thiết kế, nên khi bạn học các ràng buộc độ dài như VARCHAR(10), hãy nhớ "MySQL viết như vậy" — cú pháp đó sẽ chuyển sang được khi bạn chuyển sang các cơ sở dữ liệu khác.
-- Khai báo kiểu nghiêm ngặt trong MySQL (chỉ đọc — đừng chạy trên console này)
CREATE TABLE product (
id INT PRIMARY KEY, -- chỉ số nguyên
code CHAR(8), -- độ dài cố định, 8 ký tự
name VARCHAR(100) NOT NULL, -- tối đa 100 ký tự
note TEXT, -- chuỗi dài
price DECIMAL(10,2) NOT NULL, -- 8 chữ số + 2 chữ số thập phân
in_stock TINYINT(1) DEFAULT 0 -- cờ 0/1 cho boolean
);
-- Trong MySQL, đưa 101 ký tự vào VARCHAR(100) sẽ
-- báo lỗi hoặc bị cắt bớt tùy thiết lập.
-- Đưa 'abc' vào cột INT sẽ báo lỗi.
-- Console của khóa học này chạy được tất cả nhờ chuyển đổi kiểu ngầm định.
Tips — CHAR so với VARCHAR và khi nào dùng từng cái
`CHAR(n)` là độ dài cố định: nếu giá trị ngắn hơn n ký tự, nó được đệm khoảng trắng phía sau cho đủ n ký tự.
`VARCHAR(n)` là độ dài biến đổi: nó giữ giá trị ở độ dài thực tế (n là giới hạn trên).
Chọn `CHAR` khi: giá trị luôn có độ dài cố định, như mã quốc gia ('JP' / 'US'), mã giới tính, hoặc một phần độ dài cố định của một hash. Bố cục cố định có thể nhanh hơn một chút cho phép so sánh và tính vị trí bản ghi.
Chọn `VARCHAR` khi: độ dài thay đổi — tên, địa chỉ email, tiêu đề, mô tả, v.v. Nó chỉ chiếm không gian thực sự cần, nên dung lượng lưu trữ nhỏ hơn.
Khi chưa chắc, `VARCHAR` là mặc định an toàn hơn. Dùng CHAR cho dữ liệu có độ dài thay đổi có thể gây ra các trường hợp so sánh không khớp tinh tế vì phần đệm khoảng trắng phía sau (ví dụ 'JP' so với 'JP ' được xử lý không đồng nhất).
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2Phát biểu nào mô tả đúng cách boolean được biểu diễn trong SQL?
Câu 3Phát biểu nào mô tả đúng sự khác biệt giữa console của khóa học này (chuyển đổi kiểu ngầm định) và kiểu nghiêm ngặt của MySQL?