CREATE Database และ Tables ใน MySQL

การสร้างฐานข้อมูลและตารางเป็นขั้นตอนแรกของการจัดเก็บข้อมูลอย่างเป็นระบบ ไม่ว่าจะเป็นแอปพลิเคชันขนาดเล็กหรือระบบระดับองค์กร การออกแบบโครงสร้างที่ดีตั้งแต่ต้นจะช่วยให้ระบบทำงานได้อย่างมีประสิทธิภาพและขยายตัวได้ในอนาคต

บทความนี้จะอธิบายคำสั่ง SQL สำหรับสร้าง Database และ Tables ในระบบจัดการฐานข้อมูล MySQL ตั้งแต่พื้นฐานไปจนถึงการกำหนด Data Types, Constraints, Indexes และแนวทาง Best Practices ในการออกแบบตาราง

สร้าง Database

ใช้คำสั่ง CREATE DATABASE เพื่อสร้างฐานข้อมูลใหม่

CREATE DATABASE myapp_db;

หากต้องการป้องกัน Error กรณีที่ฐานข้อมูลมีอยู่แล้ว ให้เพิ่ม IF NOT EXISTS

CREATE DATABASE IF NOT EXISTS myapp_db;

กำหนด Character Set และ Collation

ควรกำหนด Character Set เป็น utf8mb4 เพื่อรองรับภาษาไทย อักขระ Unicode และ Emoji อย่างครบถ้วน

CREATE DATABASE myapp_db
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

utf8mb4_unicode_ci เป็น Collation ที่เปรียบเทียบตัวอักษรตามมาตรฐาน Unicode เหมาะกับภาษาส่วนใหญ่ หากต้องการ Collation ที่เร็วกว่าสำหรับภาษาอังกฤษล้วน สามารถใช้ utf8mb4_general_ci แทนได้

เลือก Database ที่จะใช้งาน

ก่อนสร้างตารางหรือทำ Query ต้องเลือกฐานข้อมูลที่จะทำงานด้วยก่อน

USE myapp_db;

ดูรายชื่อฐานข้อมูลทั้งหมดในระบบด้วยคำสั่ง

SHOW DATABASES;

สร้างตารางด้วย CREATE TABLE

ตารางประกอบด้วยคอลัมน์ที่กำหนด Data Type และ Constraint ไว้ล่วงหน้า ตัวอย่างการสร้างตารางเก็บข้อมูลผู้ใช้

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    full_name VARCHAR(100),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

คำสั่งนี้สร้างตาราง users ที่มี id เป็น Primary Key แบบ Auto Increment, username และ email ห้ามซ้ำ, password_hash ห้ามว่าง, is_active มีค่า Default เป็น TRUE และ created_at กับ updated_at บันทึกเวลาอัตโนมัติ

Data Types ที่ใช้บ่อย

ตัวเลข (Numeric)

INT — จำนวนเต็ม -2 พันล้าน ถึง 2 พันล้าน ใช้สำหรับ ID, จำนวน, ลำดับ ถ้าต้องการค่าบวกอย่างเดียว ให้ใช้ INT UNSIGNED (0 ถึง 4 พันล้าน) BIGINT — จำนวนเต็มขนาดใหญ่ ใช้เมื่อ INT ไม่พอ เช่น ID ที่มีจำนวนมาก DECIMAL(M,D) — ตัวเลขทศนิยมแม่นยำ เหมาะกับการเก็บเงิน เช่น DECIMAL(10,2) เก็บได้ถึง 99,999,999.99 FLOAT/DOUBLE — ทศนิยมแบบ Approximate เหมาะกับข้อมูลวิทยาศาสตร์ที่ไม่ต้องการความแม่นยำสูง

ข้อความ (String)

VARCHAR(n) — ข้อความความยาวไม่เกิน n ตัวอักษร ใช้พื้นที่ตามจริง เหมาะกับข้อมูลที่ยาวไม่เท่ากัน เช่น ชื่อ อีเมล CHAR(n) — ข้อความความยาวคงที่ n ตัว ใช้พื้นที่เท่ากันทุก Row เหมาะกับรหัสประเทศ (TH), รหัสสถานะ TEXT — ข้อความยาวไม่จำกัด (สูงสุด 65,535 bytes) เหมาะกับเนื้อหาบทความ รายละเอียดสินค้า ENUM — ค่าที่เลือกได้จากรายการที่กำหนดไว้ เช่น ENUM(‘active’,’inactive’,’suspended’)

วันที่และเวลา (Date/Time)

DATE — วันที่ (YYYY-MM-DD) DATETIME — วันที่และเวลา (YYYY-MM-DD HH:MM:SS) ไม่ขึ้นกับ Timezone TIMESTAMP — เหมือน DATETIME แต่แปลง Timezone อัตโนมัติ เหมาะกับการบันทึกเวลาสร้าง/แก้ไข TIME — เวลา (HH:MM:SS) ใช้เก็บระยะเวลาหรือเวลาเปิด-ปิด

อื่น ๆ

BOOLEAN — ค่า TRUE/FALSE (เก็บเป็น TINYINT 0 หรือ 1) JSON — เก็บข้อมูล JSON โดยตรง รองรับ Query ภายใน JSON Document ได้ BLOB — เก็บข้อมูล Binary เช่นไฟล์ รูปภาพ (ไม่แนะนำสำหรับไฟล์ขนาดใหญ่)

Constraints ที่สำคัญ

Constraints คือกฎที่บังคับให้ข้อมูลในตารางมีความถูกต้องและสมบูรณ์

PRIMARY KEY — ระบุ Row ที่ไม่ซ้ำกัน ทุกตารางควรมี Primary Key หนึ่งตัว NOT NULL — ห้ามเป็นค่าว่าง บังคับให้ต้องมีข้อมูล UNIQUE — ห้ามซ้ำ แต่อนุญาต NULL ได้ (ต่างจาก PRIMARY KEY) DEFAULT — กำหนดค่าเริ่มต้นเมื่อไม่ได้ระบุ CHECK — กำหนดเงื่อนไขที่ข้อมูลต้องเป็นไปตาม FOREIGN KEY — อ้างอิง Primary Key ของตารางอื่น สร้างความสัมพันธ์ระหว่างตาราง

สร้างตารางที่มี Foreign Key

Foreign Key เชื่อมโยงตารางเข้าด้วยกัน ช่วยรักษา Referential Integrity ตัวอย่างสร้างตาราง orders ที่อ้างอิง users

CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    product_name VARCHAR(200) NOT NULL,
    quantity INT NOT NULL DEFAULT 1,
    total_price DECIMAL(10,2) NOT NULL,
    status ENUM('pending','processing','shipped','delivered','cancelled') DEFAULT 'pending',
    ordered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);

ON DELETE RESTRICT ป้องกันไม่ให้ลบ User ที่ยังมี Order อยู่ ON UPDATE CASCADE ทำให้เมื่อ User ID เปลี่ยน Order จะอัพเดตตาม ตัวเลือกอื่นที่ใช้บ่อยคือ ON DELETE CASCADE (ลบ Order ตามเมื่อลบ User) และ ON DELETE SET NULL (ตั้ง user_id เป็น NULL)

สร้าง Index เพื่อเพิ่มความเร็ว

Index ช่วยให้การค้นหาข้อมูลเร็วขึ้นอย่างมาก โดยเฉพาะกับตารางที่มีข้อมูลจำนวนมาก

CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_ordered_at ON orders(ordered_at);

ควรสร้าง Index บนคอลัมน์ที่ใช้ใน WHERE, JOIN และ ORDER BY บ่อย ๆ แต่อย่าสร้างมากเกินไปเพราะจะทำให้การเขียนข้อมูลช้าลง เพราะระบบต้องอัพเดต Index ทุกครั้งที่มีการ INSERT, UPDATE หรือ DELETE

Composite Index

สำหรับ Query ที่ค้นหาด้วยหลายคอลัมน์พร้อมกัน Composite Index จะมีประสิทธิภาพสูงกว่า Index แยก

CREATE INDEX idx_orders_user_status ON orders(user_id, status);

Index นี้เหมาะกับ Query เช่น SELECT * FROM orders WHERE user_id = 5 AND status = ‘pending’ ลำดับคอลัมน์ใน Composite Index สำคัญมาก คอลัมน์แรกควรเป็นคอลัมน์ที่ใช้กรองบ่อยที่สุด

ดูโครงสร้างตาราง

ตรวจสอบโครงสร้างของตารางที่สร้างไว้ด้วยคำสั่ง

DESCRIBE users;
SHOW CREATE TABLE orders;

DESCRIBE แสดงรายชื่อคอลัมน์พร้อม Data Type, NULL, Key และ Default ส่วน SHOW CREATE TABLE แสดงคำสั่ง CREATE TABLE เต็มรูปแบบรวม Index และ Foreign Key

แก้ไขตารางด้วย ALTER TABLE

เมื่อต้องการเปลี่ยนโครงสร้างตารางหลังสร้างแล้ว ใช้ ALTER TABLE

ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;

ALTER TABLE users MODIFY COLUMN full_name VARCHAR(150);

ALTER TABLE users DROP COLUMN phone;

ALTER TABLE users RENAME COLUMN full_name TO display_name;

ADD COLUMN เพิ่มคอลัมน์ใหม่ (ระบุตำแหน่งด้วย AFTER), MODIFY COLUMN เปลี่ยน Data Type หรือ Constraint, DROP COLUMN ลบคอลัมน์ และ RENAME COLUMN เปลี่ยนชื่อ ควรระวังเมื่อทำกับตารางที่มีข้อมูลจำนวนมาก เพราะอาจใช้เวลานานและล็อคตาราง

ลบ Database และ Tables

ลบตารางด้วย DROP TABLE และลบฐานข้อมูลทั้งหมดด้วย DROP DATABASE

DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS users;
DROP DATABASE IF EXISTS myapp_db;

ต้องลบตารางที่มี Foreign Key อ้างอิงก่อนตารางที่ถูกอ้างอิง (ลบ orders ก่อน users) คำสั่ง DROP ลบข้อมูลถาวรไม่สามารถกู้คืนได้ ควรใช้อย่างระมัดระวังและสำรองข้อมูลก่อนเสมอ

Best Practices ในการออกแบบตาราง

ทุกตารางต้องมี Primary Key — ใช้ INT AUTO_INCREMENT หรือ BIGINT AUTO_INCREMENT เป็น Primary Key เพื่อให้ระบบจัดการ Index ได้อย่างมีประสิทธิภาพ หลีกเลี่ยง UUID เป็น Primary Key เพราะทำให้ Index ขนาดใหญ่และช้ากว่า

ใช้ Data Type ที่เหมาะสม — เลือก Data Type ที่เล็กที่สุดที่เพียงพอ เช่น ใช้ TINYINT แทน INT สำหรับค่า 0-255 ใช้ VARCHAR(50) แทน VARCHAR(255) ถ้าข้อมูลไม่เกิน 50 ตัว ใช้ DECIMAL สำหรับเงิน ไม่ใช่ FLOAT

ตั้งชื่อที่สื่อความหมาย — ใช้ snake_case สำหรับชื่อตารางและคอลัมน์ เช่น user_id, created_at, order_status ชื่อตารางควรเป็นพหูพจน์ (users, orders, products) เพื่อแสดงว่าเก็บหลาย Record

ใส่ created_at และ updated_at ทุกตาราง — Timestamp เหล่านี้ช่วยในการ Debug, Audit Trail และการ Sync ข้อมูล

ใช้ utf8mb4 เสมอ — อย่าใช้ utf8 (ซึ่งจริง ๆ คือ utf8mb3) เพราะไม่รองรับ Emoji และอักขระ Unicode บางตัว

สรุป

การสร้าง Database และ Tables เป็นทักษะพื้นฐานที่สำคัญ สิ่งที่ต้องจำ ได้แก่ กำหนด Character Set เป็น utf8mb4 ตั้งแต่สร้างฐานข้อมูล, ออกแบบตารางด้วย Data Type ที่เหมาะสม, ใส่ Constraints เพื่อรักษาความถูกต้องของข้อมูล, ใช้ Foreign Key เชื่อมโยงตาราง, สร้าง Index บนคอลัมน์ที่ค้นหาบ่อย และทุกตารางควรมี Primary Key กับ Timestamp เมื่อออกแบบตามแนวทางเหล่านี้ ระบบจัดการฐานข้อมูลจะทำงานได้อย่างมีประสิทธิภาพและขยายตัวได้ง่าย

แนะนำบริการ DE

หากต้องการเซิร์ฟเวอร์สำหรับรันฐานข้อมูลที่ออกแบบเองพร้อม Root Access เต็มรูปแบบ Cloud VPS ของ DE มาพร้อม SSD Storage ที่ให้ IOPS สูง เหมาะกับงานฐานข้อมูลที่ต้องการความเร็วในการอ่านเขียน

สำหรับผู้ที่ต้องการฐานข้อมูลพร้อมใช้งานโดยไม่ต้องจัดการเซิร์ฟเวอร์เอง Cloud Hosting ของ DE มาพร้อม phpMyAdmin สำหรับสร้างและจัดการตารางผ่านหน้าเว็บ เหมาะกับ WordPress และเว็บแอปพลิเคชันทั่วไป