....หลายท่านที่มีความรู้พื้นฐานเกี่ยวกับฐานข้อมูลเชิงสัมพันธ์(Relational Database)
หรือเคยผ่านการเรียนวิชาเกี่ยวกับ Database ในมหาวิทยาลัยมาคงจะรู้จัก "ความสัมพันธ์แบบ M:N (Many to Many)" ดี แต่หากท่านใดยังไม่รู้จักหรือยังไม่มีความรู้ก็อย่าเพิ่งน้อยใจแล้วก็ไม่ต้องไปหาซื้อหนังสือที่ไหนนะครับ ไปหาอ่านได้ที่เว็ป uni.net หรือใช้ google หาดูก็ได้ครับมีเยอะแยะเลย
ในบทความนี้ผมจะมาตอบสิ่งที่เป็นปัญหาในบรรดาคนทำเว็ปหลายคนไม่เว้นทั้งมือใหม่และมือเก่า ปัญหานั้นคือความเข้าใจเรื่องความสัมพันธ์ของ Database และการนำไปใช้ในทางปฏิบัติ หลายคนไม่เข้าใจตรงจุดนี้จึงทำให้มีการเก็บข้อมูลซ้ำซ้อนโดยไม่จำเป็น
ผมขอกล่าวเฉพาะ M:N และไม่ขอกล่าวทางทฤษฎีเพราะมีคนเขียนไปไว้เยอะแล้ว ส่วนความสัมพันธ์แบบอื่นนั้นคือ 1:M (One to Many) และ M:1 (Many to One) เป็นลักษณะของการ JOIN TABLE ปกติครับคิดว่าคงทำกันได้อยู่แล้วถ้า JOIN TABLE เป็น แต่ M:N นั้นมันมีทริคเพิ่มเติมอีกเล็กน้อยที่ผมกำลังจะนำเสนอ
เอาละครับมาเริ่มกันเลย
ถ้าโจทย์มีอยู่ว่า สำนักเขียนโปรแกรมสุดยอดโปรแกรมมิ่ง มีอาจารย์สอนเขียนโปรแกรมและแต่ละคนรับผิดชอบวิชาที่สอนดังนี้
| อาจารย์ | วิชาที่สอน |
| อ.อีโก้ | Java, C#.NET, PHP |
| อ.เซียน | เซียน PHP, VB, VB.NET |
| อ.เทพ | VB,VB.NET |
| อ.แอดวานซ์ | Java,C/C++,PHP |
| อ.คัมภีร์ | คัมภีร์ Java, คัมภีร์ PHP, คัมภีร์ OOP |
ถ้าเจอโจทย์แบบนี้ท่านจะออกแบบ Database อย่างไรครับ อาจเป็นแบบนี้
tb_teaching
| teacher [varchar(50)] | subject [text] |
| XXXXX | XXXXX, XXXX, XXXX |
หลายท่านอาจคิดได้ดีขึ้นหน่อย อาจเป็นแบบนี้
tb_teacher
| teacher_id [int(3)] | teacher [varchar(50)] |
| XXX | XXXXXX |
tb_subject
| subject_id [int(3)] | subject [varchar(50)] |
| XXX | XXXXXX |
tb_teaching
| teacher_id [int(3)] | subject1_id [int(3)] | subject2_id [int(3)] | subject3_id [int(3)] |
| XXXXX | XXXXX | XXXXX | XXXXX |
กรณีที่สองนี้เป็นปัญหาที่พบเห็นได้บ่อย คือ รู้จักการ JOIN และเข้าใจว่า Database ห้ามมีกลุ่มของข้อมูลซ้ำ แต่ไม่รู้ว่าจะออกแบบให้มีความสัมพันธ์แบบ M:N อย่างไร ดังนั้นทางออกจึงเป็นอย่างที่เห็น
ทีนี้เรามาดูคำตอบที่ถูกต้องกันครับ
tb_teacher
| teacher_id [int(3)] | teacher [varchar(50)] |
| XXX | XXXXXX |
tb_subject
| subject_id [int(3)] | subject [varchar(50)] |
| XXX | XXXXXX |
rel_tb_teacher_subject
| teacher_id [int(3)] | subject_id [int(3)] |
| XXX | XXX |
ทริคของการใช้งานความสัมพันธ์แบบ M:N คือการสร้าง Relation Table (หาความหมายเพิ่มเติมได้ตามเว็ปที่เขียนเกี่ยวกับ Database) ขึ้นมาเก็บคีย์หลัก (Primary Key) ของ Table ที่ต้องการสร้างความสัมพันธ์ไว้ พูดอีกอย่างก็คือ Relation Table คือ Table ที่มี คีย์หลักเป็นคีย์นอก(Foreign Keys) นั้นเอง เพราะ M:N = M:1+1:M พอจะเห็นภาพหรือยังครับ Relation Table ก็คือเครื่องหมายบวกในสมการนั้นเอง จึงเป็นตารางที่นิยมเก็บแต่คีย์ไม่เก็บข้อมูลเพราะจะมีปัญหาตอนที่ทำการ JOIN TABLE
ทำความเข้าใจเบี้องต้นกันแล้วก็มาลงมือปฏิบัติกันเลย
ขั้นแรก สร้าง Table ในฐานข้อมูลตามที่กล่าวไว้เมื่อกี้ คำสั่ง SQL ที่เห็น เป็นของ MySQL 4.0 แต่สามารถใชัในเวอร์ชันสูงกว่าได้ครับ เคยลองใช้ MySQL 5.0 แล้วพบว่าคำสั่ง SQL ใหม่ ๆ เพิ่มขึ้นเยอะมาก
| CREATE TABLE `tb_teacher` ( `teacher_id` int(3) NOT NULL auto_increment, `teacher` varchar(50) default NULL, PRIMARY KEY (`teacher_id`) ) TYPE=MyISAM; INSERT INTO `tb_teacher` VALUES (1,'อ.อีโก้'); INSERT INTO `tb_teacher` VALUES (2,'อ.เซียน'); INSERT INTO `tb_teacher` VALUES (3,'อ.เทพ'); INSERT INTO `tb_teacher` VALUES (4,'อ.แอดวานซ์'); INSERT INTO `tb_teacher` VALUES (5,'อ.คัมภีร์'); |
![]() |
| CREATE TABLE `tb_subject` ( `subject_id` int(3) NOT NULL auto_increment, `subject` varchar(50) default NULL, PRIMARY KEY (`subject_id`) ) TYPE=MyISAM; INSERT INTO `tb_subject` VALUES (1,'Java'); INSERT INTO `tb_subject` VALUES (2,'C#.NET'); INSERT INTO `tb_subject` VALUES (3,'PHP'); INSERT INTO `tb_subject` VALUES (4,'เซียน PHP'); INSERT INTO `tb_subject` VALUES (5,'VB'); INSERT INTO `tb_subject` VALUES (6,'VB.NET'); INSERT INTO `tb_subject` VALUES (7,'C/C++'); INSERT INTO `tb_subject` VALUES (8,'คัมภีร์ Java'); INSERT INTO `tb_subject` VALUES (9,'คัมภีร์ PHP'); INSERT INTO `tb_subject` VALUES (10,'คัมภีร์ OOP'); |
![]() |
| CREATE TABLE `rel_tb_teacher_subject` ( `teacher_id` int(3) NOT NULL auto_increment, `subject_id` int(3) NOT NULL default '0', PRIMARY KEY (`teacher_id`,`subject_id`) ) TYPE=MyISAM; INSERT INTO `rel_tb_teacher_subject` VALUES (1,1); INSERT INTO `rel_tb_teacher_subject` VALUES (1,2); INSERT INTO `rel_tb_teacher_subject` VALUES (1,3); INSERT INTO `rel_tb_teacher_subject` VALUES (2,4); INSERT INTO `rel_tb_teacher_subject` VALUES (2,5); INSERT INTO `rel_tb_teacher_subject` VALUES (2,6); INSERT INTO `rel_tb_teacher_subject` VALUES (3,5); INSERT INTO `rel_tb_teacher_subject` VALUES (3,6); INSERT INTO `rel_tb_teacher_subject` VALUES (4,1); INSERT INTO `rel_tb_teacher_subject` VALUES (4,3); INSERT INTO `rel_tb_teacher_subject` VALUES (4,7); INSERT INTO `rel_tb_teacher_subject` VALUES (5,8); INSERT INTO `rel_tb_teacher_subject` VALUES (5,9); INSERT INTO `rel_tb_teacher_subject` VALUES (5,10); |
![]() |
ขั้นที่สอง สร้างไฟล์ php ขึ้นมา 1 ไฟล์แล้วก็เขียนโค้ดดังนี้
<?
$link = mysql_connect("localhost","user","password"); #อย่าลืมเปลี่ยนให้เป็นของเครื่องตัวเองก่อนทดลอง ^^
mysql_select_db("test"); #ฐานข้อมูลที่ใช้
$sql = "SELECT tb_teacher.teacher_id, teacher, tb_subject.subject_id, subject FROM rel_tb_teacher_subject
INNER JOIN tb_teacher ON rel_tb_teacher_subject.teacher_id=tb_teacher.teacher_id
INNER JOIN tb_subject ON rel_tb_teacher_subject.subject_id=tb_subject.subject_id
ORDER BY tb_teacher.teacher_id, tb_subject.subject_id ASC"; #คำสั่ง SQL ที่ใช้ในการ JOIN TABLE
$result = mysql_query($sql) or die("Error : ".mysql_error());
?>
<strong>ตารางวิชาสอนของอาจารย์สำนักเขียนโปรแกรมสุดยอดโปรแกรมมิ่ง</strong><br>
<br>
<table width="600" border="1" cellspacing="0" cellpadding="0">
<tr align="center">
<td><strong>ลำดับที่</strong></td>
<td><strong>รหัสอาจารย์</strong></td>
<td><strong>ชื่ออาจารย์</strong></td>
<td><strong>รหัสวิชา</strong></td>
<td><strong>วิชาที่สอน</strong></td>
</tr>
<?
$i = 1;
while($value = mysql_fetch_array($result)){
?>
<tr>
<td><?=$i?></td>
<td><?=$value['teacher_id']?></td>
<td><?=$value['teacher']?></td>
<td><?=$value['subject_id']?></td>
<td><?=$value['subject']?></td>
</tr>
<?
$i++;
}//end while
mysql_free_result($result);
mysql_close($link);
?>
</table>
ก็จะได้ผลลัพธ์ดังนี้
ลองนำไปประยุกต์ดูนะครับ เช่นเพิ่มเงื่อนไขเข้าไปในคำสั่ง SQL เพื่อควบคุมการแสดงผลเป็นต้น
-----------------------------------------------------------------------------------------------------------
ตั้งใจมาซะนานเลยกว่าจะเขียนบทความนี้เสร็จ (ผ่านการเพาะบ่มจนได้ที่) ....อยากให้นำไปประยุกต์กันนะครับ เพราะบทความของผมเป็นแนวทำความเข้าใจเชิงลึกเพื่อการต่อยอด มีหลายท่านเข้ามาอ่านบทความของผมแล้วส่งโปรแกรมเป็นตัว ๆ มาให้แก้บั๊ก อันนี้ขออณุญาตไม่ตอบกลับเพราะเป็นการช่วยตัวท่านเองด้วยให้พยายามเอาชนะปัญหาแล้วท่านก็จะสามารถพัฒนาฝีมือตัวเองขี้นได้ แต่หากเป็นการขอคำชี้แนะหรือแนวทางอันนี้พอได้ครับ
...เป็นกำลังใจให้เว็ปไทยดี ๆ สร้างสรรค์งานดี ๆ เพื่อสังคมอย่างนี้ตลอดไปครับ
บทความหน้ายังมีอีกหลายเรื่องที่ผมอยากจะเขียน...ห้ามพลาด! ติดตามได้ที่นี่ที่เดียว (เพราะผมเขียนที่เดียว^^)
| ผู้จัดทำ : วิวัฒน์ มณีจันสุข ที่อยู่อีเมลล์ : winnerww@hotmail.com website : http://computerpsycho.saiyaithai.org |


