SQL Part 1 — DDL & Basic Queries
CREATE TABLE พร้อม integrity constraint · SELECT / FROM / WHERE · DISTINCT · rename · LIKE · ORDER BY
วิดีโอที่อาจารย์ให้ดูก่อนเรียนบทนี้ (แบ่ง 2 ตอน):
5.1SQL คืออะไร และแบ่งเป็นกลุ่มไหนบ้าง
SQL (Structured Query Language) เกิดจากภาษา Sequel ที่ IBM พัฒนาในโครงการ System R ที่ห้องวิจัย San Jose ต่อมาเปลี่ยนชื่อเป็น SQL · มาตรฐาน ANSI/ISO ไล่มาตั้งแต่ SQL-86, SQL-89, SQL-92, SQL:1999, SQL:2003
ระบบเชิงพาณิชย์ส่วนใหญ่รองรับฟีเจอร์ SQL-92 เกือบทั้งหมด บวกกับฟีเจอร์จากมาตรฐานรุ่นหลังบางส่วน และฟีเจอร์เฉพาะตัวของแต่ละเจ้า ตัวอย่างในสไลด์บางอันจึงอาจไม่ทำงานบนทุกระบบ
| กลุ่มคำสั่ง | หน้าที่ |
|---|---|
| DDL Data Definition Language |
นิยามโครงสร้าง — schema ของ relation, ชนิดข้อมูล, index, สิทธิ์ · CREATE TABLE, ALTER TABLE, DROP TABLE |
| DML Data Manipulation Language |
จัดการข้อมูลข้างใน — query · insert · delete · modify tuple · SELECT, INSERT, UPDATE, DELETE |
| Integrity | DDL มีคำสั่งสำหรับระบุ integrity constraint |
| View definition | DDL มีคำสั่งสำหรับนิยาม view |
| Transaction control | ระบุจุดเริ่มและจุดจบของ transaction |
| Embedded & dynamic SQL | กำหนดวิธีฝัง SQL ไว้ในภาษาโปรแกรมทั่วไป |
| Authorization | ระบุสิทธิ์การเข้าถึง relation และ view |
DDL ของ SQL ให้เราระบุ: schema ของแต่ละ relation · ชนิดของค่าในแต่ละ attribute · integrity constraints · ชุด index ที่ต้องดูแลของแต่ละ relation · ข้อมูลความปลอดภัยและสิทธิ์ · โครงสร้างการจัดเก็บเชิงกายภาพบนดิสก์
Domain Types ใน SQL
| ชนิด | ความหมาย |
|---|---|
| char(n) | สตริงความยาวคงที่ n ตัวอักษร |
| varchar(n) | สตริงความยาวแปรผัน ยาวสูงสุด n |
| int | จำนวนเต็ม (ช่วงขึ้นกับเครื่อง) |
| smallint | จำนวนเต็มขนาดเล็ก |
| numeric(p,d) | เลขทศนิยมตายตัว p หลักรวม ทศนิยม d ตำแหน่ง · numeric(3,1) เก็บ 44.5 ได้ แต่ 444.5 หรือ 0.32 ไม่ได้ |
| real, double precision | ทศนิยมลอยตัว ความละเอียดขึ้นกับเครื่อง |
| float(n) | ทศนิยมลอยตัว ความละเอียดอย่างน้อย n หลัก |
5.2เชื่อมต่อและสร้างฐานข้อมูล
mysql.server start -- เริ่มเซิร์ฟเวอร์
mysql -u root -p -- เชื่อมต่อ
mysql -u <username> -p <database> -- เชื่อมต่อพร้อมเลือก db เลย
CREATE DATABASE uni_demo;
USE uni_demo; -- เลือก/สลับฐานข้อมูล
SELECT DATABASE(); -- ตอนนี้ใช้ db ไหนอยู่
SHOW DATABASES; -- มี db อะไรบ้าง
SHOW TABLES; -- มีตารางอะไรบ้าง
DESCRIBE Student; -- โครงสร้างตาราง (= relation schema)
5.3CREATE TABLE และ Integrity Constraints
รูปแบบทั่วไป:
CREATE TABLE table_name (
A₁ D₁,
A₂ D₂,
…,
Aₙ Dₙ,
(integrity-constraint₁),
…,
(integrity-constraintₖ)
);
โดย Aᵢ คือชื่อ attribute และ Dᵢ คือชนิดข้อมูลของ domain ของ attribute นั้น
ชนิดของ integrity constraint ที่ต้องรู้: primary key (A₁, …, Aₙ) · foreign key (Aₘ, …, Aₙ) references r · not null
SQL จะปฏิเสธการอัปเดตใด ๆ ที่ทำให้ integrity constraint ถูกละเมิด
CREATE TABLE department (
dept_name VARCHAR(20) PRIMARY KEY,
building VARCHAR(20),
budget NUMERIC(10,0)
);
CREATE TABLE instructor (
ID CHAR(5),
name VARCHAR(20) NOT NULL,
dept_name VARCHAR(20),
salary NUMERIC(8,2),
PRIMARY KEY (ID),
FOREIGN KEY (dept_name) REFERENCES department
);
CREATE TABLE student (
ID VARCHAR(5),
name VARCHAR(20) NOT NULL,
dept_name VARCHAR(20),
tot_cred NUMERIC(3,0),
PRIMARY KEY (ID),
FOREIGN KEY (dept_name) REFERENCES department(dept_name)
);
CREATE TABLE course (
course_id VARCHAR(8),
title VARCHAR(50),
dept_name VARCHAR(20),
credits NUMERIC(2,0),
PRIMARY KEY (course_id),
FOREIGN KEY (dept_name) REFERENCES department(dept_name)
);
-- composite primary key: ต้องใช้ 4 คอลัมน์รวมกันจึงระบุ section ได้
CREATE TABLE section (
course_id VARCHAR(8),
sec_id VARCHAR(8),
semester VARCHAR(6),
year NUMERIC(4,0),
building VARCHAR(15), -- ตึกที่ใช้เรียน
room_number VARCHAR(7),
PRIMARY KEY (course_id, sec_id, semester, year)
);
-- FK แบบหลายคอลัมน์ ชี้ไปยัง composite PK ของ section
CREATE TABLE takes (
ID VARCHAR(5),
course_id VARCHAR(8),
sec_id VARCHAR(8),
semester VARCHAR(6),
year NUMERIC(4,0),
grade VARCHAR(2),
PRIMARY KEY (ID, course_id, sec_id, semester, year),
FOREIGN KEY (ID) REFERENCES student,
FOREIGN KEY (course_id, sec_id, semester, year)
REFERENCES section (course_id, sec_id, semester, year)
);
REFERENCES department ที่ไม่ใส่วงเล็บ หมายความว่าอะไรสังเกตว่า instructor เขียน
REFERENCES department เฉย ๆ แต่ student เขียน REFERENCES department(dept_name)ตามมาตรฐาน SQL (และในตำราที่อาจารย์ใช้) ละวงเล็บได้ — ถ้าไม่ระบุคอลัมน์ จะใช้ primary key ของตารางปลายทาง โดยปริยาย (PK ของ department คือ dept_name อยู่แล้ว) สองบรรทัดนี้จึงหมายความเหมือนกัน
แต่เวลาเขียนจริง ให้ระบุคอลัมน์ทุกครั้ง — อ่านง่ายกว่ามาก และระบบจริงบางตัวไม่ยอมรับแบบละวงเล็บ → เขียน
REFERENCES department(dept_name), REFERENCES student(ID) ไว้ก่อนปลอดภัยที่สุดในข้อสอบ ถ้าโจทย์ลอกมาจากสไลด์แบบละวงเล็บ ก็ตอบตามสไลด์ได้ — แต่เขียนครบไม่มีทางผิด
2. composite PK ของ section — ต้องใช้ 4 คอลัมน์รวมกันจึงชี้ได้ว่าเป็นกลุ่มเรียนไหน เพราะวิชาเดียวกันเปิดหลายกลุ่ม หลายเทอม หลายปี
3. FK ของ takes มี 2 อัน คนละแบบ —
FOREIGN KEY (ID) REFERENCES student เป็น FK คอลัมน์เดียว
ส่วน FOREIGN KEY (course_id, sec_id, semester, year) เป็น FK 4 คอลัมน์ ที่ต้องจับคู่กับ composite PK ของ section
ครบทุกคอลัมน์พร้อมกัน — ลำดับคอลัมน์ในวงเล็บต้องตรงกับลำดับที่ประกาศไว้ฝั่ง section ด้วย
เพราะการจับคู่เป็นแบบตามตำแหน่ง ไม่ใช่ตามชื่อ — สลับลำดับแล้วระบบจะเอา semester ไปเทียบกับ sec_id โดยไม่ฟ้อง error
เพิ่ม constraint ให้ตารางที่มีอยู่แล้ว
ALTER TABLE table_name ADD PRIMARY KEY (column_name);
ALTER TABLE table_name
ADD CONSTRAINT fk_name
FOREIGN KEY (column_name) REFERENCES referenced_table(referenced_column);
INSERT · DELETE · DROP
INSERT INTO instructor VALUES ('10101','Srinivasan','Comp. Sci.', 65000);
DELETE FROM instructor; -- ลบทุกแถว โครงสร้างยังอยู่
DROP TABLE instructor; -- ลบทั้งข้อมูลและโครงสร้าง
Recovery — ข้อมูลที่ลบด้วย DELETE มักกู้คืนได้ง่ายกว่า object ที่ถูก DROP
Performance — ถ้าจะลบข้อมูลทั้งหมดของตารางใหญ่ การ DROP แล้วสร้างใหม่มักเร็วกว่า DELETE
5.4โครงสร้างพื้นฐานของ Query
SELECT A₁, A₂, …, Aₙ -- attribute ที่ต้องการ
FROM r₁, r₂, …, rₘ -- relation ที่เกี่ยวข้อง
WHERE P; -- predicate
ผลลัพธ์ของ SQL query คือ relation เสมอ
SELECT clause — 5 เรื่องที่ต้องรู้
- ตรงกับ projection ใน relational algebra ·
SELECT name FROM instructor - SQL ยอมให้มีแถวซ้ำ ทั้งใน relation และในผลลัพธ์ ·
SELECT DISTINCT dept_nameเพื่อกำจัดซ้ำ ·SELECT ALL dept_nameเพื่อคงไว้ (เป็นค่าเริ่มต้น)
| ทฤษฎี (บทที่ 2–3) | SQL ของจริง (บทที่ 5) | |
|---|---|---|
| relation คืออะไร | set — แถวซ้ำกันไม่ได้ | multiset / bag — แถวซ้ำกันได้ |
| เลือกคอลัมน์ | Π ตัดแถวซ้ำให้อัตโนมัติ | SELECT ไม่ตัด — ต้องเขียน DISTINCT เอง |
ยกเว้น
UNION, INTERSECT, EXCEPT ซึ่งตัดแถวซ้ำให้เหมือนทฤษฎี — ถ้าอยากเก็บซ้ำไว้ต้องเขียน UNION ALL
SELECT *= ทุก attribute · literal ได้โดยไม่มี FROM เช่นSELECT '437'ได้ตาราง 1 คอลัมน์ 1 แถว · ตั้งชื่อคอลัมน์ด้วยSELECT '437' AS FOO- literal พร้อม FROM เช่น
SELECT 'A' FROM instructorได้ตาราง 1 คอลัมน์ N แถว (เท่าจำนวน tuple ใน instructor) ทุกแถวมีค่า 'A' - ใส่นิพจน์คณิตศาสตร์ได้ ด้วย
+ − * /บนค่าคงที่หรือ attribute ·SELECT ID, name, salary/12 AS monthly_salary FROM instructor
Name ≡ NAME ≡ name · หลายคนนิยมพิมพ์ keyword เป็นตัวใหญ่เพื่อให้อ่านง่ายแต่ค่าข้อมูลที่เป็นสตริงและ pattern ของ LIKE เป็น case-sensitive —
'Comp. Sci.' ไม่เท่ากับ 'comp. sci.'
WHERE clause
ตรงกับ selection predicate ของ relational algebra · รวมผลการเปรียบเทียบด้วย AND, OR, NOT และเปรียบเทียบผลของนิพจน์คณิตศาสตร์ได้
SELECT name FROM instructor
WHERE dept_name = 'Comp. Sci.' AND salary > 80000;
FROM clause · Cartesian product vs Join
FROM ตรงกับ Cartesian product ของ relational algebra —
SELECT * FROM instructor, teaches สร้างทุกคู่ที่เป็นไปได้ พร้อม attribute จากทั้งสอง relation
· attribute ที่ชื่อซ้ำกัน (เช่น ID) จะถูกเปลี่ยนชื่อโดยเติมชื่อ relation นำหน้า เช่น instructor.ID
SELECT name, department.dept_name
FROM instructor, department;
ฐานข้อมูลตัวอย่างในตำรา Silberschatz มี instructor 12 แถว และ department 7 แถว (ที่นี่อ้างแค่จำนวนแถว ไม่ได้แสดงข้อมูลเต็ม)
→ ทุกคู่ที่เป็นไปได้ = 12 × 7 = 84 แถว
ในนั้นมีแถวอย่าง “Mozart (Music) คู่กับ Physics” ซึ่งไม่เป็นความจริง — ส่วนใหญ่จึงไร้ความหมาย
SELECT name, department.dept_name
FROM instructor, department
WHERE instructor.dept_name = department.dept_name;
เหลือเฉพาะคู่ที่ dept_name ตรงกันจริง = อาจารย์ละ 1 แถว = 12 แถว
(อาจารย์ทุกคนสังกัดได้แผนกเดียว จาก 84 แถวจึงรอด 12 แถว ตกไป 72 แถว)
Rename ด้วย AS — และการ join ตารางกับตัวเอง
-- หาชื่ออาจารย์ที่เงินเดือนสูงกว่าอาจารย์บางคนในภาค COE
SELECT DISTINCT T.name
FROM instructor AS T, instructor AS S
WHERE T.salary > S.salary AND S.dept_name = 'COE';
คำว่า AS ละได้ — instructor AS T เท่ากับ instructor T
การให้ชื่อแทน (alias) สองชื่อกับตารางเดียวกัน ทำให้เปรียบเทียบแถวในตารางเดียวกันได้ — เรียกว่า self join
5.5String Operations และ LIKE
SQL มีตัวดำเนินการจับคู่สตริงชื่อ like ซึ่งใช้อักขระพิเศษ 2 ตัว
- เปอร์เซ็นต์
%— จับคู่กับสตริงย่อยใด ๆ (ยาว 0 ตัวขึ้นไป) - ขีดล่าง
_— จับคู่กับอักขระเดียว
| Pattern | ความหมาย |
|---|---|
| 'Intro%' | สตริงที่ขึ้นต้นด้วย "Intro" |
| '%Comp%' | สตริงที่มี "Comp" อยู่ข้างใน |
| '%ma%' | ชื่อที่มี "ma" เป็นสตริงย่อย |
| '___' | สตริงที่ยาวสามตัวพอดี |
| '___%' | สตริงที่ยาวอย่างน้อยสามตัว |
| 'The%Adventure' | ขึ้นต้นด้วย "The" และลงท้ายด้วย "Adventure" |
| '___ of%' | มีสามตัวอักษรพอดีก่อนคำว่า " of" |
| LIKE '100 \%' ESCAPE '\' | จับคู่สตริง "100 %" จริง ๆ โดยใช้ backslash เป็นอักขระ escape |
Pattern เป็น case-sensitive · SQL ยังรองรับ operation อื่นกับสตริง เช่น การต่อสตริงด้วย || ·
แปลงตัวพิมพ์ใหญ่เป็นเล็กและกลับกัน · หาความยาว · ตัดสตริงย่อย
โจทย์แบบฝึกหัดข้อ 4 — เขียน LIKE ให้ถูก
a) หนังสือที่ชื่อขึ้นต้นด้วย "The" และลงท้ายด้วย "Adventure" โดยมีอักขระกี่ตัวก็ได้ตรงกลาง
SELECT title FROM books WHERE title LIKE 'The%Adventure';
ได้: The Great Adventure, The Last Jungle Adventure, The Adventure (เพราะ % จับคู่กับช่องว่างตัวเดียวได้)
ไม่ได้: The Adventure Begins เพราะไม่ได้ลงท้ายด้วย Adventure · A Grand Adventure เพราะไม่ได้ขึ้นต้นด้วย The
b) หนังสือที่มีสามตัวอักษรพอดีก่อนคำว่า "of"
SELECT title FROM books WHERE title LIKE '___ of%';
ได้: Age of Empires, Art of War, Sea of Stars
ไม่ได้: Lord of the Rings (4 ตัว), Book of Life (4 ตัว), An of Grammar (2 ตัว)
5.6ORDER BY และ Predicate เพิ่มเติม
SELECT DISTINCT name FROM instructor ORDER BY name;
SELECT * FROM instructor ORDER BY name DESC;
SELECT * FROM instructor ORDER BY dept_name, name; -- เรียงหลายคอลัมน์
ASC เป็นค่าเริ่มต้น · ระบุ DESC เพื่อเรียงจากมากไปน้อย · กำหนดทิศทางแยกกันแต่ละคอลัมน์ได้
-- BETWEEN: รวมปลายทั้งสองข้าง (>= 60000 AND <= 80000)
SELECT name FROM instructor WHERE salary BETWEEN 60000 AND 80000;
Tuple comparison — เปรียบเทียบหลายคอลัมน์พร้อมกัน
SQL ให้เราเอาคอลัมน์หลายตัวมาใส่วงเล็บแล้วเทียบเป็นชุดเดียว ผลลัพธ์เป็นจริงก็ต่อเมื่อตรงกันครบทุกตำแหน่ง — ตำแหน่งที่ 1 เทียบกับตำแหน่งที่ 1, ตำแหน่งที่ 2 เทียบกับตำแหน่งที่ 2
-- สองบรรทัดนี้ให้ผลเหมือนกันทุกประการ
WHERE (course_id, sec_id) = ('CS-101', '1')
WHERE course_id = 'CS-101' AND sec_id = '1'
ใช้จริงตอนไหน — เมื่อคีย์มีหลายคอลัมน์ (composite key) การเขียนเป็นชุดจะสั้นและอ่านง่ายกว่า:
-- นักศึกษาที่ลงเรียนกลุ่ม CS-101 sec 1 ของ Fall 2017
SELECT ID, grade
FROM takes
WHERE (course_id, sec_id, semester, year) = ('CS-101', '1', 'Fall', 2017);
WHERE (course_id, sec_id, semester, year) IN (
SELECT course_id, sec_id, semester, year
FROM section WHERE building = 'Watson' )
ถ้าไม่มีไวยากรณ์นี้ ต้องเขียนเป็น join หรือ EXISTS ที่ยาวกว่ามากระวัง: ลำดับคอลัมน์ในวงเล็บซ้ายต้องตรงกับลำดับใน SELECT ของ subquery เป๊ะ ๆ สลับกันไม่ได้ — เพราะการจับคู่เป็นแบบตามตำแหน่ง ไม่ใช่ตามชื่อ สลับแล้วระบบจะเทียบผิดคู่โดยไม่ฟ้อง error
5.7โจทย์แบบฝึกหัดในคาบ พร้อมเฉลย
ทุกข้อข้างล่างใช้ชุดข้อมูลนี้ (ตั้งชื่อตารางแบบพหูพจน์ตามใบงาน) — เปิดดูควบคู่กับเฉลยจะเห็นภาพ
| ID | name | dept_name | salary |
|---|---|---|---|
| 1001 | Somchai | COE | 95000 |
| 1002 | Manee | COE | 120000 |
| 1003 | Chujai | COE | 90000 |
| 1004 | Preecha | EE | 110000 |
| course_id | title | department | credit |
|---|---|---|---|
| 9101 | Database Systems | COE | 3 |
| 9102 | Data Structures | COE | 3 |
| 9201 | Circuit Analysis | EE | 3 |
| ID | name | dept_name |
|---|---|---|
| 6601 | Nara | COE |
| 6602 | Beam | COE |
| 6603 | Chompoo | COE |
| 6604 | Dew | EE |
| 6605 | Earn | COE |
| ID | course_id | grade |
|---|---|---|
| 6601 | 9101 | A |
| 6602 | 9101 | B |
| 6603 | 9101 | B+ |
| 6603 | 9102 | A |
| 6604 | 9201 | C |
Earn (6605) ไม่มีแถวใน takes เลย
ข้อ 1 — สร้างตาราง courses และ departments พร้อม constraint ที่เหมาะสม
CREATE TABLE IF NOT EXISTS departments (
dept_name VARCHAR(50) PRIMARY KEY,
building_name VARCHAR(50)
);
CREATE TABLE IF NOT EXISTS courses (
course_id INT PRIMARY KEY,
title VARCHAR(60) NOT NULL,
department VARCHAR(50),
credit INT CHECK (credit > 0),
FOREIGN KEY (department) REFERENCES departments(dept_name)
);
สร้าง departments ก่อนเสมอ เพราะ courses อ้างอิงมันด้วย FK — ถ้าสร้างสลับกันจะ error ว่าตารางปลายทางไม่มีอยู่
ข้อ 2 — หาอาจารย์ในภาค COE ที่เงินเดือนเกิน 90,000
SELECT * FROM instructors
WHERE dept_name = 'COE' AND salary > 90000;
ไล่ทีละแถวจากตาราง instructors ข้างบน → ได้ Somchai (95,000) และ Manee (120,000)
ระวัง: Chujai ได้ 90,000 พอดี → ไม่ผ่าน เพราะโจทย์ใช้ > ไม่ใช่ >= · Preecha (110,000) อยู่ EE จึงไม่เข้าเงื่อนไข
ข้อ 3 — หานักศึกษาทุกคนที่เคยลงวิชาในภาค COE
SELECT DISTINCT s.ID, s.name
FROM students s, takes t, courses c
WHERE s.ID = t.ID
AND t.course_id = c.course_id
AND c.department = 'COE';
หรือเขียนด้วย JOIN แบบชัดเจน (บทที่ 6):
SELECT DISTINCT s.ID, s.name
FROM students s
JOIN takes t ON s.ID = t.ID
JOIN courses c ON t.course_id = c.course_id
WHERE c.department = 'COE';
ชื่อคอลัมน์ต้องตรงกับที่ประกาศไว้ในข้อ 1 — ในตาราง courses คอลัมน์ชื่อ
department ไม่ใช่ dept_name (ที่เป็นชื่อคอลัมน์ในตาราง departments)
เขียนผิดจะได้ ERROR 1054: Unknown column 'c.dept_name'
ไล่ผลลัพธ์ทีละขั้นจากข้อมูลข้างบน:
- วิชาของ COE = {9101, 9102} (9201 เป็นของ EE)
- แถวใน takes ที่ course_id อยู่ในเซตนั้น = (6601,9101), (6602,9101), (6603,9101), (6603,9102) → 4 แถว
- join กับ students แล้วเอาชื่อ → Nara, Beam, Chompoo, Chompoo
DISTINCTยุบ Chompoo ที่ซ้ำ → Nara, Beam, Chompoo (3 คน)
ทำไมต้อง DISTINCT: Chompoo ลงวิชา COE ไว้ 2 วิชา จึงมี 2 แถวใน takes ที่ผ่านเงื่อนไข
ถ้าไม่ใส่ DISTINCT จะได้ 4 แถว โดยมีชื่อ Chompoo โผล่มา 2 ครั้ง
คนที่ไม่เข้าเงื่อนไข: Dew ลงแค่ 9201 ซึ่งเป็นวิชาของ EE · Earn ไม่มีแถวใน takes เลย
ข้อ 4 เป็นโจทย์ LIKE — เฉลยอยู่ใน §5.5 เพราะต้องใช้เรื่อง pattern matching
ข้อ 5 — INSERT ไหนสำเร็จ ไหนล้มเหลว เพราะอะไร
ข้อนี้ใช้ schema เล็ก ๆ ของตัวเอง (ไม่ใช่ชุดข้อมูลด้านบน) ตามที่โจทย์กำหนดมา:
CREATE TABLE Departments (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL
);
CREATE TABLE Employees (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(50),
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES Departments(dept_id)
);
INSERT INTO Departments VALUES (1,'HR'), (2,'IT');
-- ตอนนี้ Departments มีอยู่แค่ 2 แถว: dept_id = 1 และ 2 เท่านั้น
a) INSERT INTO Employees VALUES (101, 'John Doe', 2); -- สำเร็จ
b) INSERT INTO Employees VALUES (102, 'Jane Smith', 4); -- ล้มเหลว
a) สำเร็จ — dept_id = 2 มีอยู่จริงใน Departments (IT) จึงผ่าน foreign key constraint
b) ล้มเหลว — dept_id = 4 ไม่มีอยู่ใน Departments · FK constraint บังคับว่าค่าใน referencing relation
ต้องปรากฏเป็นค่า primary key ของ referenced relation จึงเกิด error
ERROR 1452: Cannot add or update a child row: a foreign key constraint fails
นี่คือ referential integrity ทำงาน — ฐานข้อมูลกันข้อมูลขยะให้เราตั้งแต่ต้นทาง
5.8สรุปบทนี้
- DDL สำหรับสร้างและแก้ไขโครงสร้างฐานข้อมูล
- DML สำหรับ query และแก้ไขข้อมูล
- โครงสร้างพื้นฐาน SELECT · FROM · WHERE ตรงกับ Π · × · σ ตามลำดับ
- Integrity constraints รักษาความสอดคล้องของข้อมูล
- String operations และการจับคู่ pattern ด้วย LIKE
- การเรียงลำดับและกรองผลลัพธ์
SELECT 'A' FROM instructor; เมื่อ instructor มี 12 แถว จะได้ผลลัพธ์อย่างไรFROM จะถูกคืนออกมา 1 แถวต่อ 1 tuple ในตาราง · ถ้าไม่มี FROM เช่น SELECT '437' จะได้แค่แถวเดียว — สองกรณีนี้ต่างกันWHERE title LIKE '___%' จับคู่กับข้อใด_ สามตัว = อักขระ 3 ตัวพอดี แล้ว % = อีกกี่ตัวก็ได้ (รวมทั้ง 0 ตัว) → อย่างน้อย 3 ตัว · ถ้าอยากได้ 3 ตัวพอดีต้องใช้ '___' เฉย ๆ