SQL คืออะไร? คู่มือ Structured Query Language ฉบับครบ
แอปแทบทุกแบบที่คุณใช้ ตั้งแต่โซเชียลมีเดีย ธนาคาร ไปจนถึงอีคอมเมิร์ซ ล้วนเก็บข้อมูลในฐานข้อมูลเชิงสัมพันธ์และดึงข้อมูลด้วย SQL การเข้าใจ SQL จึงเป็นทักษะสำคัญสำหรับงานพัฒนา software, data analysis และ IT
สารบัญ
- SQL คืออะไร?
- ประวัติย่อของ SQL
- อธิบายฐานข้อมูลเชิงสัมพันธ์
- พื้นฐาน SQL Syntax
- CRUD Operations
- การกรอง การเรียงลำดับ และการสรุปผล
- JOINs: การรวมตาราง
- Subqueries และ CTEs
- Indexes และ Performance
- Transactions และ ACID
- เปรียบเทียบ SQL Dialects
- SQL Injection และความปลอดภัย
- แนวทางปฏิบัติที่ดี
- SQL เทียบกับ NoSQL
- แหล่งอ้างอิง
SQL คืออะไร?
SQL ย่อมาจาก Structured Query Language เป็นภาษามาตรฐานสำหรับสร้าง query, แก้ไข และจัดการข้อมูลใน ฐานข้อมูลเชิงสัมพันธ์
SQL เป็นภาษาแบบ declarative คือคุณบอกว่าต้องการข้อมูลอะไร ส่วน database engine จะตัดสินใจเองว่าจะดึงข้อมูลอย่างมีประสิทธิภาพอย่างไร จึงต่างจากภาษาแบบเขียนขั้นตอน เช่น JavaScript หรือ Python
SQL ยังเป็นเทคโนโลยีหลัก เพราะใช้กับฐานข้อมูลอย่าง PostgreSQL, MySQL, SQLite, SQL Server, Oracle Database และระบบ analytics จำนวนมาก
การออกเสียง
SQL อ่านได้ทั้งแบบ "sequel" และแบบสะกดทีละตัวว่า "S-Q-L" ทั้งสองแบบเป็นที่เข้าใจทั่วไป ทีมงานมักใช้ตามชุมชนหรือระบบฐานข้อมูลที่ทำงานด้วย
ประวัติย่อของ SQL
SQL เริ่มจาก relational model ของ Edgar F. Codd ในปี 1970 จากนั้น Donald Chamberlin และ Raymond Boyce จาก IBM สร้าง SEQUEL ซึ่งต่อมากลายเป็น SQL เพื่อใช้ query ข้อมูลเชิงสัมพันธ์
| ปี | เหตุการณ์สำคัญ |
|---|---|
| 1970 | Edgar F. Codd เผยแพร่แนวคิด relational model |
| 1974 | IBM พัฒนา SEQUEL ซึ่งต่อมาถูกเปลี่ยนชื่อเป็น SQL |
| 1979 | Oracle เปิดตัวฐานข้อมูล SQL เชิงพาณิชย์รุ่นแรก |
| 1986 | SQL กลายเป็นมาตรฐาน ANSI |
| 1992 | SQL-92 เพิ่มความสามารถสำคัญด้าน JOIN และ expressions |
| 1999 | SQL:1999 เพิ่ม triggers, CTEs และ recursive queries |
| 2016-2023 | มาตรฐาน SQL ยุคใหม่เพิ่ม JSON และ graph query features |
อธิบายฐานข้อมูลเชิงสัมพันธ์
ฐานข้อมูลเชิงสัมพันธ์จัดข้อมูลเป็นตาราง โดยแต่ละตารางมักประกอบด้วย:
- Columns หรือคอลัมน์ สำหรับกำหนด field เช่น name, email, price หรือ created_at
- Rows หรือแถว โดยแต่ละแถวคือหนึ่ง record
- Primary keys สำหรับระบุแถวแบบไม่ซ้ำ
- Foreign keys สำหรับเชื่อมข้อมูลระหว่างตาราง
users(id, name, email)
orders(id, user_id, total, order_date)
orders.user_id -> users.idโครงสร้างนี้ช่วยลดข้อมูลซ้ำ เช่น รายละเอียดลูกค้าเก็บไว้ครั้งเดียวในตาราง users แล้วตาราง orders อ้างถึงลูกค้าด้วย id
พื้นฐาน SQL Syntax
คำสั่ง SQL มักแบ่งออกเป็นหมวดหมู่ดังนี้:
| หมวดหมู่ | คำสั่ง | จุดประสงค์ |
|---|---|---|
| DQL | SELECT | ดึงข้อมูล |
| DML | INSERT, UPDATE, DELETE | แก้ไขข้อมูล |
| DDL | CREATE, ALTER, DROP | กำหนด schema และ tables |
| DCL | GRANT, REVOKE | ควบคุมสิทธิ์ |
| TCL | BEGIN, COMMIT, ROLLBACK | จัดการ transactions |
SELECT users.name, orders.total
FROM users
JOIN orders ON orders.user_id = users.id
WHERE orders.total > 100
ORDER BY orders.total DESC;CRUD Operations
CRUD หมายถึง create, read, update และ delete ซึ่งเป็นการทำงานพื้นฐานที่แอปส่วนใหญ่ทำกับข้อมูลที่เก็บไว้
-- Create
INSERT INTO products (name, price) VALUES ('Keyboard', 49.99);
-- Read
SELECT id, name, price FROM products WHERE price > 20;
-- Update
UPDATE products SET price = 44.99 WHERE id = 1;
-- Delete
DELETE FROM products WHERE id = 1;การกรอง การเรียงลำดับ และการสรุปผล
Query จริงมักต้องกรองแถว เรียงผลลัพธ์ จัดกลุ่มข้อมูล และคำนวณค่าสรุป เช่น count, sum, average, minimum และ maximum
WHEREใช้กรองแถวORDER BYใช้เรียงผลลัพธ์GROUP BYใช้จัดกลุ่มเพื่อสรุปผลHAVINGใช้กรองผลลัพธ์หลังจัดกลุ่ม
JOINs: การรวมตาราง
JOINs ใช้รวมข้อมูลจากหลายตาราง เป็นความสามารถสำคัญที่ทำให้ฐานข้อมูลเชิงสัมพันธ์แทนความสัมพันธ์จริงได้โดยไม่ต้องคัดลอกข้อมูลซ้ำไปทุกที่
- INNER JOIN: คืนเฉพาะแถวที่ match กันทั้งสองตาราง
- LEFT JOIN: คืนทุกแถวจากตารางซ้าย พร้อมแถวที่ match จากตารางขวา
- RIGHT JOIN: คืนทุกแถวจากตารางขวา พร้อมแถวที่ match จากตารางซ้าย
- FULL OUTER JOIN: คืนแถวจากทั้งสองฝั่ง และจับคู่เมื่อ match กัน
SELECT users.name, orders.order_date, orders.total
FROM users
INNER JOIN orders ON orders.user_id = users.id;Subqueries และ CTEs
Subquery คือ query ที่อยู่ภายในอีก query หนึ่ง ส่วน CTE ที่เขียนด้วย WITH ใช้ตั้งชื่อ result set ชั่วคราว เพื่อให้ SQL ที่ซับซ้อนอ่านง่ายและนำไปใช้ต่อได้
Indexes และ Performance
Index คือโครงสร้างข้อมูลที่ช่วยให้ฐานข้อมูลค้นหาแถวได้เร็วขึ้น มักใช้ B-tree เป็นพื้นฐาน Index ช่วยเร่งการอ่าน แต่ใช้พื้นที่เพิ่ม และอาจทำให้การเขียนช้าลง เพราะ INSERT, UPDATE หรือ DELETE ต้องปรับ index ด้วย
CREATE INDEX idx_products_category ON products(category);
EXPLAIN SELECT * FROM products WHERE category = 'Electronics';ข้อแลกเปลี่ยนของ Index
อย่า index ทุกคอลัมน์ ให้เน้นคอลัมน์ที่ใช้บ่อยใน WHERE, JOIN, ORDER BY และ uniqueness checks แล้วตรวจสอบผลด้วย EXPLAIN
Transactions และ ACID
| คุณสมบัติ | ความหมาย |
|---|---|
| Atomicity | ทุก operation สำเร็จทั้งหมด หรือ rollback ทั้งหมด |
| Consistency | ฐานข้อมูลย้ายจากสถานะที่ถูกต้องหนึ่งไปสู่อีกสถานะที่ถูกต้อง |
| Isolation | Transactions ที่ทำพร้อมกันไม่ทำให้ข้อมูลเสียหายกันเอง |
| Durability | ข้อมูลที่ commit แล้วต้องยังอยู่แม้ระบบล่ม |
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
-- ROLLBACK;เปรียบเทียบ SQL Dialects
แม้ SQL จะมีมาตรฐาน แต่ฐานข้อมูลแต่ละตัวก็เพิ่ม feature และ syntax เฉพาะของตัวเอง
| Feature | MySQL | PostgreSQL | SQLite | SQL Server |
|---|---|---|---|---|
| Auto-increment | AUTO_INCREMENT | SERIAL / GENERATED | AUTOINCREMENT | IDENTITY |
| จำกัดจำนวนแถว | LIMIT | LIMIT | LIMIT | TOP / OFFSET-FETCH |
| ต่อ string | CONCAT() | || | || | + |
| Upsert | ON DUPLICATE KEY | ON CONFLICT | ON CONFLICT | MERGE |
| รองรับ JSON | JSON type | JSONB | JSON functions | JSON functions |
SQL Injection และความปลอดภัย
SQL injection เกิดขึ้นเมื่อเอา input จากผู้ใช้มาต่อเป็น SQL โดยตรง ผู้โจมตีอาจเปลี่ยนความหมายของ query และอ่าน แก้ไข หรือลบข้อมูลได้
-- Vulnerable: string concatenation
query = "SELECT * FROM users WHERE name = '" + userInput + "'";
-- Safe: parameterized query
query = "SELECT * FROM users WHERE name = ?";
db.execute(query, [userInput]);ใช้ Parameterized Queries เสมอ
อย่าต่อ user input เข้าไปใน SQL string โดยตรง ให้ใช้ prepared statements หรือ parameterized queries เพื่อให้ input ถูกมองเป็นข้อมูล ไม่ใช่ SQL ที่รันได้
แนวทางปฏิบัติที่ดี
- จัดรูปแบบ SQL ให้สม่ำเสมอ ใช้ keyword ตัวใหญ่และ indentation ที่อ่านง่าย เครื่องมือ SQL formatter ช่วยได้
- ตั้งชื่อตารางและคอลัมน์ให้สื่อความหมาย
- หลีกเลี่ยง
SELECT *ใน production query และเลือกเฉพาะคอลัมน์ที่ต้องใช้ - เพิ่ม indexes อย่างมีกลยุทธ์ และตรวจสอบด้วย
EXPLAIN - ใช้ transactions สำหรับการเปลี่ยนแปลงที่ต้องสำเร็จหรือ fail พร้อมกัน
- ใช้ parameterized queries กับค่าที่มาจากผู้ใช้ทุกครั้ง
- สำรองข้อมูลสม่ำเสมอ และทดสอบขั้นตอนการ restore ด้วย
SQL เทียบกับ NoSQL
NoSQL databases เช่น MongoDB, Redis, Cassandra และ DynamoDB เหมาะกับงานบางแบบที่ relational model ไม่ใช่คำตอบที่ดีที่สุด
| ด้าน | SQL | NoSQL |
|---|---|---|
| Data model | ตารางที่มี rows และ columns | Documents, key-value, graph หรือ wide-column |
| Schema | กำหนด schema ชัดเจน | schema ยืดหยุ่น |
| Scaling | มักเริ่มจาก vertical scaling | มักเริ่มจาก horizontal scaling |
| Consistency | รองรับ ACID เข้มแข็ง | มักเป็น eventual หรือตั้งค่าได้ |
| เหมาะกับ | ข้อมูลมีโครงสร้างและ transactions | ข้อมูลยืดหยุ่นและ workload ปริมาณสูง |
ในทางปฏิบัติ ระบบสมัยใหม่จำนวนมากใช้ทั้งสองแบบ เช่น SQL สำหรับข้อมูลธุรกรรมอย่าง users และ orders และ NoSQL สำหรับ caching, search, events หรือ document storage
จัดรูปแบบ SQL ได้ทันที
ใช้ SQL Formatter ฟรีของเราเพื่อ beautify, indent และจัดมาตรฐาน SQL queries รองรับ dialect ที่พบบ่อย และทำงานในเบราว์เซอร์ของคุณ
ลองใช้ SQL Formatter ->แหล่งอ้างอิง
- Codd, E. F. A Relational Model of Data for Large Shared Data Banks. https://dl.acm.org/doi/10.1145/362384.362685
- ISO/IEC 9075:2023. Information technology - Database languages - SQL.
- OWASP Foundation. SQL Injection. https://owasp.org/www-community/attacks/SQL_Injection
- PostgreSQL Global Development Group. PostgreSQL Documentation. https://www.postgresql.org/docs/
- MySQL. MySQL Reference Manual. https://dev.mysql.com/doc/