สอน SQL และ Database ฉบับสมบูรณ์ 2026: MySQL PostgreSQL จนถึง NoSQL MongoDB

สอน SQL และ Database ฉบับสมบูรณ์ 2026: MySQL PostgreSQL จนถึง NoSQL MongoDB

sql database guide 2026
· 3500 คำ · หมวด: tech
SQLDatabaseMySQLPostgreSQLMongoDBNoSQLDatabase DesignORM

ในยุคที่ข้อมูลคือหัวใจของทุกแอปพลิเคชัน ไม่ว่าจะเป็นเว็บไซต์ แอปมือถือ หรือระบบ Enterprise การเข้าใจ SQL และ Database อย่างถ่องแท้คือทักษะพื้นฐานที่นักพัฒนาทุกคนต้องมี บทความนี้จะพาคุณเดินทางตั้งแต่พื้นฐาน SQL ไปจนถึงการออกแบบฐานข้อมูล การเปรียบเทียบ MySQL กับ PostgreSQL และโลกของ NoSQL อย่าง MongoDB พร้อมตัวอย่างโค้ดจริงที่ใช้งานได้ทันที

Database คืออะไร: RDBMS vs NoSQL

Database (ฐานข้อมูล) คือระบบที่ใช้จัดเก็บ จัดการ และเรียกค้นข้อมูลอย่างมีโครงสร้าง ฐานข้อมูลแบ่งออกเป็นสองประเภทหลักที่มีปรัชญาการออกแบบแตกต่างกันอย่างสิ้นเชิง

RDBMS (Relational Database Management System)

ฐานข้อมูลเชิงสัมพันธ์จัดเก็บข้อมูลในรูปแบบตาราง (Table) ที่มีแถว (Row) และคอลัมน์ (Column) โดยใช้ภาษา SQL ในการจัดการ ข้อมูลจะถูกเชื่อมโยงกันผ่าน Primary Key และ Foreign Key ทำให้มีความสัมพันธ์ที่ชัดเจนระหว่างข้อมูลชุดต่างๆ ตัวอย่าง RDBMS ที่นิยม ได้แก่ MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server และ SQLite

จุดเด่นของ RDBMS คือการรับประกัน ACID Properties ซึ่งประกอบด้วย Atomicity (ทำทั้งหมดหรือไม่ทำเลย), Consistency (ข้อมูลต้องถูกต้องเสมอ), Isolation (แต่ละ Transaction ไม่กระทบกัน) และ Durability (ข้อมูลที่ Commit แล้วจะไม่สูญหาย) ทำให้เหมาะกับระบบที่ต้องการความถูกต้องของข้อมูลสูง เช่น ระบบธนาคาร ระบบบัญชี หรือระบบ E-commerce

NoSQL (Not Only SQL)

ฐานข้อมูลแบบ NoSQL ออกแบบมาเพื่อรองรับข้อมูลที่มีโครงสร้างหลากหลายและปริมาณมหาศาล แบ่งออกเป็นหลายประเภท ได้แก่ Document Store (MongoDB), Key-Value Store (Redis), Column-family Store (Cassandra) และ Graph Database (Neo4j) NoSQL เน้น Horizontal Scaling คือการเพิ่มเครื่องเพื่อรองรับภาระงานที่มากขึ้น แทนที่จะอัพเกรดเครื่องเดิม

SQL พื้นฐาน: คำสั่งที่ต้องรู้

SELECT, WHERE และ ORDER BY

คำสั่ง SELECT เป็นคำสั่งที่ใช้บ่อยที่สุดในการดึงข้อมูลจากฐานข้อมูล เราสามารถกำหนดเงื่อนไขด้วย WHERE, เรียงลำดับด้วย ORDER BY และจำกัดจำนวนผลลัพธ์ด้วย LIMIT

-- ดึงข้อมูลพนักงานที่เงินเดือนมากกว่า 50000 เรียงจากมากไปน้อย
SELECT id, name, department, salary
FROM employees
WHERE salary > 50000
  AND department = 'Engineering'
ORDER BY salary DESC
LIMIT 10;

-- ใช้ LIKE สำหรับการค้นหาแบบ Pattern
SELECT * FROM products
WHERE name LIKE '%laptop%'
  AND price BETWEEN 20000 AND 50000;

-- ใช้ IN สำหรับหลายค่า
SELECT * FROM orders
WHERE status IN ('pending', 'processing', 'shipped')
  AND created_at >= '2026-01-01';

GROUP BY และ Aggregate Functions

การจัดกลุ่มข้อมูลด้วย GROUP BY ร่วมกับฟังก์ชัน Aggregate เป็นเครื่องมือสำคัญในการวิเคราะห์ข้อมูล ฟังก์ชันพื้นฐาน ได้แก่ COUNT() นับจำนวน, SUM() รวมค่า, AVG() หาค่าเฉลี่ย, MAX() หาค่าสูงสุด, MIN() หาค่าต่ำสุด

-- สรุปยอดขายรายเดือนของแต่ละแผนก
SELECT department,
       DATE_FORMAT(sale_date, '%Y-%m') AS month,
       COUNT(*) AS total_orders,
       SUM(amount) AS total_revenue,
       AVG(amount) AS avg_order_value,
       MAX(amount) AS max_order
FROM sales
GROUP BY department, DATE_FORMAT(sale_date, '%Y-%m')
HAVING SUM(amount) > 100000
ORDER BY total_revenue DESC;

INSERT, UPDATE, DELETE: การจัดการข้อมูล

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

-- INSERT: เพิ่มข้อมูล
INSERT INTO employees (name, email, department, salary, hired_date)
VALUES ('สมชาย ใจดี', 'somchai@company.com', 'Engineering', 65000, CURDATE());

-- INSERT หลายแถวพร้อมกัน (Batch Insert — เร็วกว่า INSERT ทีละแถว)
INSERT INTO products (name, price, category) VALUES
  ('Keyboard Mechanical', 2500, 'peripheral'),
  ('Mouse Wireless', 890, 'peripheral'),
  ('Monitor 27 inch', 8900, 'display');

-- UPDATE: แก้ไขข้อมูล (ระวัง! ต้องมี WHERE เสมอ)
UPDATE employees
SET salary = salary * 1.10,
    updated_at = NOW()
WHERE department = 'Engineering'
  AND performance_rating >= 4;

-- DELETE: ลบข้อมูล (ระวัง! ต้องมี WHERE เสมอ)
DELETE FROM logs
WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY);
คำเตือนสำคัญ: UPDATE หรือ DELETE โดยไม่มี WHERE จะกระทบทุกแถวในตาราง! ควรรัน SELECT ก่อนเพื่อตรวจสอบข้อมูลที่จะถูกแก้ไข และใช้ Transaction (BEGIN/COMMIT) เสมอ

JOIN Types: การเชื่อมข้อมูลข้ามตาราง

JOIN เป็นหัวใจของ Relational Database ที่ช่วยเชื่อมข้อมูลจากหลายตารางเข้าด้วยกัน การเลือก JOIN ที่ถูกต้องส่งผลต่อทั้งผลลัพธ์และประสิทธิภาพ

INNER JOIN

ดึงเฉพาะแถวที่มีข้อมูลตรงกันในทั้งสองตาราง หากฝั่งใดฝั่งหนึ่งไม่มีข้อมูลที่ตรงกัน แถวนั้นจะไม่ปรากฏในผลลัพธ์

-- INNER JOIN: ดึงออเดอร์พร้อมชื่อลูกค้า
SELECT o.id AS order_id, c.name AS customer_name,
       o.total_amount, o.order_date
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id
WHERE o.order_date >= '2026-01-01';

LEFT JOIN (LEFT OUTER JOIN)

ดึงทุกแถวจากตารางซ้าย และแถวที่ตรงกันจากตารางขวา หากตารางขวาไม่มีข้อมูลจะแสดงเป็น NULL เหมาะสำหรับกรณีที่ต้องการดูข้อมูลทั้งหมดจากตารางหลัก

-- LEFT JOIN: ดูลูกค้าทุกคน รวมทั้งคนที่ยังไม่เคยสั่งซื้อ
SELECT c.name, c.email,
       COUNT(o.id) AS order_count,
       COALESCE(SUM(o.total_amount), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id, c.name, c.email
ORDER BY total_spent DESC;

RIGHT JOIN และ FULL OUTER JOIN

RIGHT JOIN ทำงานตรงข้ามกับ LEFT JOIN คือดึงทุกแถวจากตารางขวา ส่วน FULL OUTER JOIN ดึงทุกแถวจากทั้งสองตาราง (MySQL ไม่รองรับโดยตรง ต้องใช้ UNION)

-- FULL OUTER JOIN ใน PostgreSQL
SELECT e.name AS employee, d.name AS department
FROM employees e
FULL OUTER JOIN departments d ON e.department_id = d.id;

-- จำลอง FULL OUTER JOIN ใน MySQL ด้วย UNION
SELECT e.name AS employee, d.name AS department
FROM employees e LEFT JOIN departments d ON e.department_id = d.id
UNION
SELECT e.name, d.name
FROM employees e RIGHT JOIN departments d ON e.department_id = d.id;

CROSS JOIN

สร้าง Cartesian Product ระหว่างสองตาราง คือจับคู่ทุกแถวจากตารางแรกกับทุกแถวจากตารางที่สอง มักใช้ในการสร้างข้อมูลชุดค่าผสม

-- CROSS JOIN: สร้าง Matrix ขนาด/สีสินค้า
SELECT p.name, s.size_label, c.color_name
FROM products p
CROSS JOIN sizes s
CROSS JOIN colors c
WHERE p.category = 'clothing';

Subquery และ CTE (Common Table Expressions)

Subquery และ CTE ช่วยแบ่ง Query ที่ซับซ้อนออกเป็นส่วนย่อยๆ ที่เข้าใจง่ายขึ้น CTE มักอ่านง่ายกว่า Subquery และสามารถอ้างอิงซ้ำได้

-- Subquery: หาพนักงานที่เงินเดือนสูงกว่าค่าเฉลี่ยของแผนก
SELECT name, department, salary
FROM employees e
WHERE salary > (
    SELECT AVG(salary)
    FROM employees e2
    WHERE e2.department = e.department
);

-- CTE: วิเคราะห์ลูกค้า VIP (สั่งซื้อมากกว่า 10 ครั้งและยอดรวมเกิน 100,000)
WITH customer_stats AS (
    SELECT customer_id,
           COUNT(*) AS order_count,
           SUM(total_amount) AS total_spent,
           AVG(total_amount) AS avg_order
    FROM orders
    WHERE order_date >= '2025-01-01'
    GROUP BY customer_id
),
vip_customers AS (
    SELECT cs.*, c.name, c.email
    FROM customer_stats cs
    JOIN customers c ON cs.customer_id = c.id
    WHERE cs.order_count >= 10 AND cs.total_spent >= 100000
)
SELECT * FROM vip_customers
ORDER BY total_spent DESC;

Index: ทำไมสำคัญและทำงานอย่างไร

Index คือโครงสร้างข้อมูลที่ช่วยให้ฐานข้อมูลค้นหาข้อมูลได้เร็วขึ้นอย่างมาก โดยไม่ต้องสแกนทุกแถวในตาราง (Full Table Scan) เปรียบเสมือนสารบัญในหนังสือที่ช่วยให้เราหาหน้าที่ต้องการได้ทันที

ประเภทของ Index

ประเภทวิธีการทำงานเหมาะกับ
B-Treeโครงสร้างต้นไม้แบบสมดุล ค้นหา O(log n)การค้นหาแบบช่วง, เรียงลำดับ, เปรียบเทียบ
Hashใช้ Hash Function แมปค่า O(1)การค้นหาแบบ exact match เท่านั้น
CompositeIndex หลายคอลัมน์Query ที่ WHERE หลายเงื่อนไขเสมอ
CoveringIndex ที่ครอบคลุมทุกคอลัมน์ที่ต้องการหลีกเลี่ยงการอ่านตารางหลัก
-- สร้าง Index พื้นฐาน
CREATE INDEX idx_employees_department ON employees(department);

-- Composite Index (ลำดับคอลัมน์สำคัญมาก!)
CREATE INDEX idx_orders_customer_date
ON orders(customer_id, order_date DESC);

-- Unique Index ป้องกันข้อมูลซ้ำ
CREATE UNIQUE INDEX idx_users_email ON users(email);

-- ตรวจสอบว่า Query ใช้ Index หรือไม่ด้วย EXPLAIN
EXPLAIN SELECT * FROM orders
WHERE customer_id = 123 AND order_date >= '2026-01-01';
หลักการสร้าง Index: สร้าง Index บนคอลัมน์ที่ใช้ใน WHERE, JOIN, ORDER BY บ่อยๆ แต่อย่าสร้างมากเกินไปเพราะจะทำให้ INSERT/UPDATE ช้าลง เพราะทุกครั้งที่มีการเปลี่ยนแปลงข้อมูล ฐานข้อมูลต้องอัพเดท Index ด้วย

Database Design: Normalization และ ERD

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

Normal Forms

1NF (First Normal Form): ทุกคอลัมน์ต้องมีค่า Atomic (ค่าเดียว ไม่ใช่ลิสต์) และแต่ละแถวต้องไม่ซ้ำกัน ตัวอย่างที่ผิด: คอลัมน์ phone เก็บ "081-1234567, 089-9876543" ต้องแยกเป็นตาราง phone_numbers

2NF (Second Normal Form): ผ่าน 1NF แล้วและทุก Non-key Column ต้องขึ้นอยู่กับ Primary Key ทั้งหมด ไม่ใช่แค่บางส่วน (กรณี Composite Key) เช่น ถ้า PK คือ (order_id, product_id) แต่ customer_name ขึ้นอยู่กับ order_id เท่านั้น ต้องแยกออก

3NF (Third Normal Form): ผ่าน 2NF แล้วและไม่มี Transitive Dependency คือ Non-key Column ต้องไม่ขึ้นอยู่กับ Non-key Column อื่น เช่น ถ้ามี department_id → department_name ในตาราง employees ต้องแยก department_name ไปอยู่ตาราง departments

-- ตัวอย่าง Database Design: ระบบ E-commerce
CREATE TABLE customers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(200) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    stock INT DEFAULT 0,
    category_id INT,
    FOREIGN KEY (category_id) REFERENCES categories(id)
);

CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    customer_id INT NOT NULL,
    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    status ENUM('pending','confirmed','shipped','delivered','cancelled'),
    total_amount DECIMAL(12,2),
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

CREATE TABLE order_items (
    id INT AUTO_INCREMENT PRIMARY KEY,
    order_id INT NOT NULL,
    product_id INT NOT NULL,
    quantity INT NOT NULL,
    unit_price DECIMAL(10,2) NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

MySQL vs PostgreSQL: เปรียบเทียบ

MySQL และ PostgreSQL เป็นสอง RDBMS โอเพนซอร์สที่นิยมมากที่สุดในปัจจุบัน แต่ละตัวมีจุดเด่นที่แตกต่างกัน

คุณสมบัติMySQLPostgreSQL
ปรัชญาความเร็วและง่ายต่อการใช้งานความถูกต้องและฟีเจอร์ครบถ้วน
ACID Complianceรองรับ (InnoDB)รองรับเต็มรูปแบบ
JSON SupportJSON type พื้นฐานJSONB (Binary, index ได้, เร็วกว่า)
Full-text Searchรองรับ (InnoDB)รองรับ + tsvector + Ranking
ReplicationMaster-Slave, Group ReplicationStreaming, Logical Replication
ExtensionจำกัดPostGIS, pg_trgm, TimescaleDB ฯลฯ
Window Functionsรองรับ (8.0+)รองรับครบถ้วน (มีมานาน)
ผู้ใช้หลักFacebook, Twitter, UberApple, Instagram, Spotify
เหมาะกับเว็บแอปทั่วไป, CMS, E-commerceระบบซับซ้อน, GIS, Analytics

แนะนำการเลือก

เลือก MySQL ถ้าต้องการความง่าย เริ่มต้นเร็ว และมี Community ใหญ่ มี Hosting รองรับมาก ใช้กับ WordPress, Laravel, CMS ทั่วไป

เลือก PostgreSQL ถ้าต้องการฟีเจอร์ขั้นสูง เช่น JSONB, Full-text Search, GIS (PostGIS) หรือต้องการ Standard SQL compliance สูง เหมาะกับระบบที่ซับซ้อนและต้องการ Scalability

NoSQL: MongoDB, Redis, Cassandra, DynamoDB

NoSQL ไม่ใช่คู่แข่งของ SQL แต่เป็นเครื่องมือที่เหมาะกับงานที่แตกต่างกัน แต่ละประเภทมีจุดเด่นเฉพาะตัว

MongoDB (Document Store)

เก็บข้อมูลในรูปแบบ Document (BSON/JSON) ยืดหยุ่นสูง Schema ไม่ตายตัว เหมาะกับข้อมูลที่โครงสร้างเปลี่ยนแปลงบ่อยหรือมี Nested Data ซับซ้อน

// MongoDB: เพิ่มและค้นหาข้อมูลสินค้า
db.products.insertOne({
  name: "Mechanical Keyboard",
  price: 2500,
  specs: {
    switch_type: "Cherry MX Blue",
    layout: "TKL",
    rgb: true
  },
  tags: ["keyboard", "mechanical", "gaming"],
  reviews: [
    { user: "john", rating: 5, comment: "Great!" },
    { user: "jane", rating: 4, comment: "Good value" }
  ]
});

// ค้นหาสินค้าที่มี rating >= 4 และราคาไม่เกิน 3000
db.products.find({
  price: { $lte: 3000 },
  "reviews.rating": { $gte: 4 }
}).sort({ price: 1 });

Redis (Key-Value / In-Memory)

ฐานข้อมูลแบบ In-Memory ที่เร็วมาก อ่าน/เขียนได้ภายในหลักไมโครวินาที นิยมใช้เป็น Cache Layer, Session Store, Rate Limiter, Real-time Leaderboard และ Message Queue (Pub/Sub)

Cassandra (Column-family)

ออกแบบมาเพื่อรองรับ Write-heavy Workload ขนาดใหญ่ มี Linear Scalability และ No Single Point of Failure เหมาะกับ IoT Data, Time-series Data และ Logging ระดับ Enterprise

DynamoDB (AWS Managed)

บริการ NoSQL แบบ Serverless ของ AWS ที่ Scale อัตโนมัติ จ่ายตามการใช้งาน เหมาะกับ Serverless Architecture และแอปที่ต้องการ Latency ต่ำมากในระดับ single-digit milliseconds

SQL vs NoSQL: เลือกอย่างไร

เกณฑ์เลือก SQLเลือก NoSQL
โครงสร้างข้อมูลชัดเจน ไม่ค่อยเปลี่ยนยืดหยุ่น เปลี่ยนบ่อย
ความสัมพันธ์ข้อมูลมี Relation ซับซ้อนข้อมูลค่อนข้าง Independent
Consistencyต้องการ Strong Consistencyยอมรับ Eventual Consistency ได้
ScaleVertical Scaling หลักHorizontal Scaling ง่าย
Transactionต้องการ Multi-row Transactionไม่จำเป็นมาก
ตัวอย่างงานE-commerce, Banking, ERPSocial Media, IoT, Real-time Analytics
เคล็ดลับ: หลายระบบในปัจจุบันใช้ทั้ง SQL และ NoSQL ร่วมกัน เรียกว่า Polyglot Persistence เช่น ใช้ PostgreSQL เก็บข้อมูล Transaction + Redis เป็น Cache + Elasticsearch สำหรับ Full-text Search เลือกเครื่องมือที่เหมาะกับงานแต่ละส่วน

Database Optimization: ทำให้เร็วขึ้น

EXPLAIN — วิเคราะห์ Query Plan

คำสั่ง EXPLAIN แสดงแผนการทำงานของ Query ว่าฐานข้อมูลจะค้นหาข้อมูลอย่างไร ใช้ Index หรือไม่ ช่วยให้เราปรับปรุง Query ที่ช้าได้ตรงจุด

-- MySQL: EXPLAIN ANALYZE (8.0+)
EXPLAIN ANALYZE
SELECT c.name, COUNT(o.id) as order_count
FROM customers c
JOIN orders o ON c.id = o.customer_id
WHERE o.order_date >= '2026-01-01'
GROUP BY c.id
HAVING order_count > 5;

-- PostgreSQL: EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders
WHERE customer_id = 123
ORDER BY order_date DESC
LIMIT 10;

Slow Query Log

เปิดใช้ Slow Query Log เพื่อจับ Query ที่ใช้เวลานาน เป็นเครื่องมือสำคัญในการตรวจจับปัญหาประสิทธิภาพ

-- MySQL: เปิด Slow Query Log
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- จับ Query ที่นานกว่า 1 วินาที
SET GLOBAL log_queries_not_using_indexes = 'ON';

-- PostgreSQL: ตั้งค่าใน postgresql.conf
-- log_min_duration_statement = 1000  -- Query นานกว่า 1000ms

Connection Pooling

การสร้าง Database Connection มีต้นทุนสูง Connection Pooling ช่วยรียูส Connection ที่มีอยู่แทนการสร้างใหม่ทุกครั้ง ลด Overhead อย่างมาก เครื่องมือยอดนิยม ได้แก่ PgBouncer สำหรับ PostgreSQL, ProxySQL สำหรับ MySQL หรือใช้ Pool ใน Application Level เช่น HikariCP (Java) หรือ SQLAlchemy Pool (Python)

Backup & Recovery

การ Backup เป็นสิ่งสำคัญที่สุดอย่างหนึ่งในการดูแลฐานข้อมูล ไม่มีระบบใดที่ปลอดภัย 100% จาก Hardware Failure, Human Error หรือ Ransomware

# MySQL: mysqldump (Logical Backup)
mysqldump -u root -p --single-transaction \
  --routines --triggers --all-databases > backup_full.sql

# MySQL: Restore
mysql -u root -p < backup_full.sql

# PostgreSQL: pg_dump
pg_dump -Fc -Z 9 -U postgres mydb > mydb.dump

# PostgreSQL: Restore
pg_restore -U postgres -d mydb mydb.dump

# MongoDB: mongodump
mongodump --uri="mongodb://localhost:27017/mydb" --out=/backup/
mongorestore --uri="mongodb://localhost:27017/mydb" /backup/mydb/

กฎ 3-2-1 Backup

เก็บ Backup อย่างน้อย 3 ชุด บน 2 สื่อจัดเก็บที่ต่างกัน (เช่น Local Disk + Cloud Storage) โดย 1 ชุดต้องอยู่นอกสถานที่ (Off-site) ทดสอบ Restore เป็นประจำเพื่อให้แน่ใจว่า Backup ใช้งานได้จริง

ORM: SQLAlchemy, Prisma, TypeORM

ORM (Object-Relational Mapping) ช่วยให้เราทำงานกับฐานข้อมูลผ่าน Object ในภาษาโปรแกรม แทนการเขียน SQL โดยตรง ลด Boilerplate Code และช่วยป้องกัน SQL Injection

# Python + SQLAlchemy ORM
from sqlalchemy import create_engine, Column, Integer, String, Float
from sqlalchemy.orm import declarative_base, Session

Base = declarative_base()

class Product(Base):
    __tablename__ = 'products'
    id = Column(Integer, primary_key=True)
    name = Column(String(200), nullable=False)
    price = Column(Float, nullable=False)
    category = Column(String(50))

engine = create_engine('postgresql://user:pass@localhost/mydb')
Base.metadata.create_all(engine)

with Session(engine) as session:
    # เพิ่มสินค้า
    product = Product(name="Keyboard", price=2500, category="peripheral")
    session.add(product)
    session.commit()

    # ค้นหาสินค้า
    products = session.query(Product).filter(
        Product.price < 3000,
        Product.category == "peripheral"
    ).order_by(Product.price.desc()).all()
// TypeScript + Prisma ORM
// schema.prisma
model Product {
  id       Int     @id @default(autoincrement())
  name     String
  price    Float
  category String?
}

// ใช้งาน Prisma Client
const products = await prisma.product.findMany({
  where: {
    price: { lte: 3000 },
    category: "peripheral"
  },
  orderBy: { price: "desc" }
});
ORM vs Raw SQL: ใช้ ORM สำหรับ CRUD ทั่วไป แต่สำหรับ Query ที่ซับซ้อนมากๆ (Report, Analytics) ควรเขียน Raw SQL เพื่อควบคุมประสิทธิภาพได้ดีกว่า หลายระบบนิยมใช้ Query Builder (Knex.js, Kysely) เป็นจุดกลางระหว่าง ORM กับ Raw SQL

ข้อผิดพลาดที่พบบ่อย

FAQ — คำถามที่พบบ่อย

Q: เริ่มต้นเรียน SQL ควรใช้ฐานข้อมูลอะไร?
A: แนะนำ SQLite สำหรับเริ่มต้น เพราะติดตั้งง่ายมาก ไม่ต้องตั้ง Server แค่สร้างไฟล์ .db ก็ใช้ได้ จากนั้นค่อยขยับไป MySQL หรือ PostgreSQL เมื่อต้องการฟีเจอร์เพิ่มเติม

Q: ฐานข้อมูลรองรับข้อมูลได้กี่แถว?
A: ไม่มีขีดจำกัดตายตัว ขึ้นอยู่กับ Hardware และการออกแบบ MySQL/PostgreSQL จัดการตารางที่มีหลายพันล้านแถวได้ ถ้าออกแบบ Index และ Partition ดี

Q: ควรใช้ UUID หรือ Auto-increment เป็น Primary Key?
A: Auto-increment เร็วกว่าและ Index เล็กกว่า แต่ UUID เหมาะกับระบบ Distributed ที่ต้องสร้าง ID โดยไม่ต้องถามฐานข้อมูลส่วนกลาง หรือระบบที่ไม่ต้องการเปิดเผยลำดับข้อมูล

Q: ถ้ามีข้อมูลหลักสิบล้านแถว ควรทำอย่างไร?
A: ใช้ Partitioning แบ่งตารางตามเกณฑ์ (เช่น ตามวันที่ หรือ Range), สร้าง Index ที่เหมาะสม, ใช้ Read Replica สำหรับ Query ที่อ่านอย่างเดียว และพิจารณา Archiving ข้อมูลเก่า

Q: Docker เหมาะกับ Database จริงหรือ?
A: สำหรับ Development และ Testing เหมาะมาก เพราะตั้ง Environment ได้เร็ว แต่สำหรับ Production ต้องจัดการเรื่อง Persistent Volume, Backup Strategy และ Performance Tuning อย่างรอบคอบ อ่านเพิ่มเติมใน คู่มือ Docker ฉบับสมบูรณ์

SQL คือ Database คือ ฐานข้อมูล MySQL PostgreSQL MongoDB NoSQL สอน SQL ภาษาไทย คู่มือ Database Design Normalization JOIN Index Optimization สอน database ภาษาไทย ORM SQLAlchemy Prisma