|
|
การใช้งานความสัมธ์แบบ M:N ภาคปฏิบัติ
จัดทำโดย : อ้ายคำปัน |
|
|
การใช้งานความสัมธ์แบบ M:N ภาคปฏิบัติ
บทความนี้ทีแรกผมตั้งใจจะเขียนเกี่ยวกับ "การทำ output buffering" แต่ก็พบความไม่ชัดเจนหลายอย่างจึงขอยกไปเขียนในโอกาสต่อไป
....หลายท่านที่มีความรู้พื้นฐานเกี่ยวกับฐานข้อมูลเชิงสัมพันธ์(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 |
ลักไก่แบบนี้ขอบอกว่าผิดครับเพราะกฏข้อแรกของ Database คือห้ามมีกลุ่มของข้อมูลซ้ำครับ
หลายท่านอาจคิดได้ดีขึ้นหน่อย อาจเป็นแบบนี้
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 |
จำนวนฟิลด์ subjectX_id เพิ่มตามจำนวนวิชาสูงสุดที่อาจารย์แต่ละท่านจะสามารถสอนได้
กรณีที่สองนี้เป็นปัญหาที่พบเห็นได้บ่อย คือ รู้จักการ 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 เพื่อควบคุมการแสดงผลเป็นต้น
-----------------------------------------------------------------------------------------------------------
ตั้งใจมาซะนานเลยกว่าจะเขียนบทความนี้เสร็จ (ผ่านการเพาะบ่มจนได้ที่) ....อยากให้นำไปประยุกต์กันนะครับ เพราะบทความของผมเป็นแนวทำความเข้าใจเชิงลึกเพื่อการต่อยอด มีหลายท่านเข้ามาอ่านบทความของผมแล้วส่งโปรแกรมเป็นตัว ๆ มาให้แก้บั๊ก อันนี้ขออณุญาตไม่ตอบกลับเพราะเป็นการช่วยตัวท่านเองด้วยให้พยายามเอาชนะปัญหาแล้วท่านก็จะสามารถพัฒนาฝีมือตัวเองขี้นได้ แต่หากเป็นการขอคำชี้แนะหรือแนวทางอันนี้พอได้ครับ
...เป็นกำลังใจให้เว็ปไทยดี ๆ สร้างสรรค์งานดี ๆ เพื่อสังคมอย่างนี้ตลอดไปครับ
บทความหน้ายังมีอีกหลายเรื่องที่ผมอยากจะเขียน...ห้ามพลาด! ติดตามได้ที่นี่ที่เดียว (เพราะผมเขียนที่เดียว^^)
Download Source Code
|
|