Câu 1Khi bạn chạy ALTER TABLE table ADD COLUMN status TEXT DEFAULT 'active'; trên một bảng đã tồn tại, điều gì xảy ra với cột status ở các dòng hiện có?
Thêm/đổi ràng buộc và định nghĩa lại bảng
Dùng bảng legacy_user, học cách bổ sung cột bằng ALTER TABLE ADD COLUMN ... DEFAULT và cách dựng lại bảng để biến email thành NOT NULL UNIQUE (CREATE mới → INSERT SELECT → DROP → RENAME) — tất cả thực hành trực tiếp trên trình duyệt.
Dữ liệu sẽ dùng — legacy_user
Các bảng trong sản xuất thường hóa ra cần các ràng buộc không có trong thiết kế ban đầu.
Những thứ như "gắn một giá trị mặc định cho cột này", "làm email không trùng (UNIQUE)", hoặc "đánh dấu trường bắt buộc này là NOT NULL".
Bài viết này đề cập việc thêm cột và bổ sung giá trị mặc định, và quy trình dựng lại bảng để thêm ràng buộc vào một bảng đã tồn tại.
ALTER TABLE ADD COLUMN — bổ sung cột và giá trị mặc định
Để thêm một cột mới vào bảng đã tồn tại, dùng ALTER TABLE table ADD COLUMN col_name type constraint.
Gắn DEFAULT value đặt giá trị mặc định được dùng khi cột bị bỏ qua, và vào lúc ALTER giá trị này cũng lấp đầy mọi dòng hiện có.
ADD COLUMN thậm chí chấp nhận NOT NULL khi kết hợp với DEFAULT (các dòng hiện có được lấp bằng mặc định, nên không vi phạm NOT NULL).
Mặt khác, ADD COLUMN không thể trực tiếp gắn UNIQUE hoặc một NOT NULL không kèm mặc định.
Những thứ đó cần một "dựng lại bảng".
-- Thêm một cột với DEFAULT (dùng bảng tạm để xem hành vi)
DROP TABLE IF EXISTS alter_demo;
CREATE TABLE alter_demo(id INTEGER PRIMARY KEY, name TEXT);
INSERT INTO alter_demo VALUES (1,'Alice'),(2,'Bob');
-- Thêm created_on với một DEFAULT → các dòng hiện có cũng nhận giá trị
ALTER TABLE alter_demo ADD COLUMN created_on TEXT DEFAULT '2024-01-01';
-- NOT NULL cũng ổn khi kết hợp với DEFAULT
ALTER TABLE alter_demo ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
SELECT * FROM alter_demo ORDER BY id;
Thêm ràng buộc sau khi tạo nghĩa là dựng lại bảng
Trong MySQL bạn có thể gắn ràng buộc trực tiếp vào bảng đã tồn tại, như ALTER TABLE legacy_user ADD CONSTRAINT uq_email UNIQUE (email);.
Trong console của khóa học này, bổ sung UNIQUE hoặc NOT NULL vào bảng đã tồn tại đi qua quy trình dựng lại bảng: "tạo một bảng mới với các ràng buộc bạn muốn, sao chép dữ liệu hiện có sang, và thay thế bảng cũ".
MySQL / PostgreSQL cũng thực hiện mẫu dựng lại này nội bộ cho một số thao tác (như đổi kiểu cột), tùy theo công cụ.
Quy trình theo hình dưới: tắt kiểm tra khóa ngoại, rồi CREATE bảng mới → sao chép mọi dòng → DROP bảng cũ → RENAME bảng mới → khôi phục kiểm tra.
Về ADD CONSTRAINT / AUTO_INCREMENT / comment cột của MySQL
Cú pháp ALTER TABLE ... ADD CONSTRAINT, AUTO_INCREMENT, và comment cột (COMMENT '...') trình bày dưới đây là cú pháp MySQL.
Console trên trình duyệt của khóa học này không thể chạy chúng, nên hai khối code này chỉ đọc (đừng cố thực thi).
Trong console của khóa học này, hãy bổ sung ràng buộc qua dựng lại bảng ở phần dưới, và dùng INTEGER PRIMARY KEY để đánh số tự động.
-- Cú pháp MySQL (đừng chạy trong console của khóa học — chỉ đọc)
-- MySQL: gắn một ràng buộc UNIQUE trực tiếp vào bảng đã tồn tại
ALTER TABLE legacy_user ADD CONSTRAINT uq_email UNIQUE (email);
-- MySQL: đổi sang NOT NULL qua MODIFY
ALTER TABLE legacy_user MODIFY email VARCHAR(255) NOT NULL;
-- MySQL: đánh số tự động là thuộc tính cột AUTO_INCREMENT; mô tả là comment cột
CREATE TABLE member (
member_id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE COMMENT 'login email'
);
-- Trong console của khóa học này, đạt tương đương AUTO_INCREMENT qua INTEGER PRIMARY KEY
CREATE TABLE member (
member_id INTEGER PRIMARY KEY,
email TEXT NOT NULL UNIQUE
);
-- Khung dựng lại bảng (dùng bảng tạm rebuild_demo để xem hành vi)
DROP TABLE IF EXISTS rebuild_demo;
CREATE TABLE rebuild_demo(id INTEGER PRIMARY KEY, email TEXT);
INSERT INTO rebuild_demo VALUES (1,'a@example.com'),(2,'b@example.com');
-- ① Tắt kiểm tra khóa ngoại
PRAGMA foreign_keys=OFF;
-- ② Bảng mới với ràng buộc mong muốn (email NOT NULL UNIQUE)
CREATE TABLE rebuild_demo_new(
id INTEGER PRIMARY KEY,
email TEXT NOT NULL UNIQUE
);
-- ③ Sao chép dữ liệu hiện có sang
INSERT INTO rebuild_demo_new(id, email)
SELECT id, email FROM rebuild_demo;
-- ④ Xóa bảng cũ, ⑤ đổi tên bảng mới thành tên cũ
DROP TABLE rebuild_demo;
ALTER TABLE rebuild_demo_new RENAME TO rebuild_demo;
-- ⑥ Khôi phục kiểm tra khóa ngoại
PRAGMA foreign_keys=ON;
-- Xác nhận ràng buộc đã có (email trùng giờ sẽ báo lỗi)
SELECT sql FROM sqlite_master WHERE name='rebuild_demo';
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2Console của khóa học này dùng phương pháp nào để bổ sung ràng buộc UNIQUE vào bảng đã tồn tại?
Câu 3Vì sao bạn chạy PRAGMA foreign_keys=OFF; ở đầu dựng lại bảng và khôi phục thành ON ở cuối?