Thaimisc.com : PHP กับฐานข้อมูล MySQL (23)
ThaiMisc.Com : Free Webboard | Free GuestBook | Free Poll | Free Ecard Server | Free Java Chat Room | Advertising | Contact Us | Colocation | Web Hosting | เปิดร้านค้าฟรี


Category : Php Developer Print Article Only Print Aticle With Comment
PHP กับฐานข้อมูล MySQL (23)
เขียนโดย เดอะกาฝากไดอารี่ (ball@bbznet.com) , 17-07-2004

แทรกระเบียนก็เป็นแล้ว อัพเดตแก้ไขระเบียนก็สอนไปแล้ว เพิ่ม/แก้ไขฟิลด์ในตารางก็พูดถึงไปแล้ว และล่าสุดก็ว่ากันด้วยเรื่องของการลบข้อมูลในตารางฐานข้อมูลไปแล้ว ต่อไปนี้ก็จะพูดถึงบทสุดท้ายของพื้นฐานการสร้างฐานข้อมูล เพื่อใช้ในแอปพลิเคชันที่จะพัฒนาครับ... และหลังจากนั้น ก็จะเริ่มวางโครงการ เพื่อลองประยุกต์สิ่งที่สอนๆ ไปทั้งหมด ให้เป็นเว็บแอปพลิเคชั่นครับ (ในขณะเดียวกันก็จะสอนเพิ่มเติมด้วยเลย)

ณ จุดนี้ เรามีตารางชื่อ employee ใช้ในการเก็บข้อมูลพนักงาน... ถามว่าเพียงพอหรือไม่?!? สำหรับบริษัทเล็กๆ พนักงานไม่กี่สิบคน มีแผนก 4-5 แผนก ฐานข้อมูลพื้นๆ แบบนี้ก็ไม่น่าจะติดปัญหาอะไร แต่ถ้าเป็นบริษัทใหญ่ๆ ที่มีความซับซ้อนขององค์กรมากๆ ถามว่าตาราง employee ที่ออกแบบมา มันมีช่องโหว่ตรงไหน?!?

คำตอบก็คือ ความยืดหยุ่นยังไม่ดีพอ และยังมีความสิ้นเปลืองอยู่ครับ... ยังไงล่ะ?!?

ยืดหยุ่นไม่ดีพอ
การระบุชื่อแผนกลงไปในฐานข้อมูล ด้วยการพิมพ์ตรงๆ เช่น IT, Personnel ฯลฯ สำหรับข้อมูลแต่ละระเบียน ทำให้แอปพลิเคชั่นไม่ต้องเขียนมาแบบซับซ้อนยุ่งยาก แต่ขณะเดียวกัน ก็ทำความยุ่งยากให้กับผู้ใช้งานด้วย เพราะจะต้องพิมพ์ข้อมูลลงไปให้ถูกต้องชัดเจน เช่น อยู่ฝ่ายธุรการและบุคคล ก็ต้องพิมพ์ Personnel ให้ถูกต้อง จะไปพิมพ์ผิดเป็น Personal ไม่ได้

แต่ไอ้ของแบบนี้มันผิดพลาดกันได้ครับ จริงไหมล่ะ?!?

แล้วทีนี้ปัญหาก็จะเกิดอีตอนที่เราจะทำการสืบค้นข้อมูล เช่น

SELECT * FROM employee WHERE department = "Personnel"

ผลก็คือ ระเบียนที่กรอกข้อมูลฟิลด์ department ผิดไปเป็น Personal จะไม่ถูกแสดงผลออกมา ส่งผลให้ข้อมูลที่ได้คลาดเคลื่อน...

เกิดความสิ้นเปลือง
เวลาที่เราต้องการจะเปลี่ยนชื่อแผนก เช่น Production ไปเป็น Production and Service เราก็ต้องเขียนโค้ดเปลี่ยนแบบนี้

UPDATE employee SET department = "Production and Service" WHERE department = "Production"

อาจจะดูแล้วไม่ได้ลำบากยากเย็นอะไร แต่ลองคำนวณง่ายๆ แบบนี้ดีกว่าครับ...

Production and Service มีทั้งหมด 22 ตัวอักษร ก็มีค่า 22 ไบต์... เกิดมีพนักงาน 500 คนที่ใช้ชื่อแผนกนี้ ก็เท่ากับกินเนื้อที่ฐานข้อมูล 22 x 500 = 11,000 ไบต์ หรือ 11 กิโลไบต์ นี่ไม่นับพนักงานคนอื่นๆ ที่ใช้ชื่อแผนกยาวๆ เช่นกัน

ตัวอย่างที่ยกไป อาจจะดูแล้วไม่น่าจะเป็นผลเสียอะไรมาก แต่มันก็คือความสูญเสียจริงไหมล่ะครับ?!? แล้วเราจะทำยังไงดี?!?

ยิ่งถ้าเกิดมีตารางฐานข้อมูลมากกว่า 1 ตาราง ที่ต้องมีฟิลด์ที่เก็บข้อมูลเดียวกัน จะยิ่งทำให้สิ้นเปลืองมากขึ้น... เช่นอะไรบ้าง?!? พอดีตัวอย่างที่เป็นฐานข้อมูลรายชื่อพนักงานจะไม่สามารถแสดงให้เห็นความสิ้นเปลืองตรงนี้ได้ ขอให้นึกถึงฐานข้อมูลสต็อกสินค้าครับ

ในฐานข้อมูลสต็อกสินค้า ในตารางเก็บสินค้า (inventory) เราจะมีการอ้างอิงถึงตัวผู้จัดจำหน่ายสินค้ามาให้เรา หรือที่เรียกว่า supplier และในขณะเดียวกัน ตารางใบกำกับภาษีที่เก็บข้อมูลการชำระสินค้า (invoice) เราก็มีการอ้างอิงถึงตัว supplier เช่นเดียวกัน ซึ่งทุกระเบียนใน inventory จะต้องมีการอ้างอิงถึงตัว invoice แต่เราไม่สามารถเอาข้อมูล supplier ไปเก็บไว้ที่ตาราง inventory เพียงตารางเดียวได้ เนื่องจากสินค้าชนิดเดียวกัน อาจจะมาได้จาก supplier ต่างราย

การเก็บข้อมูลด้วยการพิมพ์เป็นข้อความ จะเกิดผิดพลาดได้ง่าย หากต้องพิมพ์ข้อความเดียวกันลงไปในตาราง 2 ตาราง... จริงไหมครับ

แล้วเราจะแก้กันยังไง?!?

ตารางตระกูล Master
อันนี้ไม่ได้คิดค้นขึ้นมาเองนะครับ แต่เป็นอะไรที่ครูพักลักจำเอามาจากบรรดาแอปพลิเคชั่นอื่นๆ น่ะ... เป็นวิธีการที่จะช่วยแก้ปัญหาข้างต้นได้อย่างชะงัด นั่นก็คือ การสร้างตารางฐานข้อมูลอีกอันขึ้นมาเพื่อเก็บข้อมูลเหล่านี้แทน นั่นก็หมายความว่า ด้วยวิธีนี้...

  • เราจะเปลี่ยนฟิลด์ department จากเดิมเป็น VARCHAR ไปเป็น dept_id ที่เป็น tinyint แทน (คงไม่มีบริษัทไหนที่มีจำนวนแผนกมากมายขนาดเก็บลงฟิลด์แบบ tinyint ไม่หมดหรอกนะ) หรือฟิลด์สำหรับเก็บหมายเลขแทนชื่อแผนก/ฝ่าย
  • จากนั้นเราก็สร้างตารางใหม่ขึ้นมา สมมติว่าชื่อ department_mstr เอามาเก็บรายชื่อแผนก/ฝ่าย ต่างๆ ในบริษัท โดยมีฟิลด์ด้วยกัน 2 ฟิลด์คือ dept_id และ dept_name ซึ่งก็คือ หมายเลขแทนชื่อแผนก/ฝ่าย และชื่อแผนก/ฝ่าย ที่แทนด้วยหมายเลขนั้นๆ

ดังนั้น ตารางข้อมูลเราก็จะกลายเป็นแบบนี้ครับ (สำหรับการเปลี่ยนแปลงแก้ไข/สร้าง ตารางฐานข้อมูลนั้น จะไม่ขอกล่าวถึง จะขอให้ผู้อ่านใช้วิชาที่ศึกษามาลองทำดูนะครับ... ใครที่ไม่ชำนาญการเขียนในตอนนี้ ก็ใช้ phpMyAdmin ช่วยไปก็ได้ครับ)


ตาราง employee ที่แก้ไขแล้ว


ตาราง department_mstr ที่เพิ่มเข้ามา

ด้วยหลักการเดียวกัน เราจะเห็นว่า ชื่อตำแหน่งของพนักงานแต่ละคน ก็มีซ้ำๆ กันได้ และมีสิทธิ์ที่จะทำให้เกิดการผิดพลาดในการกรอกข้อมูลได้ หากผู้ใช้งานต้องพิมพ์เองทั้งหมด ดังนั้นเราก็ควรจะเพิ่มตารางชื่อ position_mstr เอาไว้สำหรับเก็บรายชื่อตำแหน่งต่างๆ เพื่อแทนที่ด้วยหมายเลขรหัสแทน ดังเช่นตาราง department_mstr

ดังนั้นเราจะได้ตาราง employee ใหม่ และ ตาราง position_mstr ดังนี้


ตาราง employee ที่แก้ไขอีกรอบ


ตาราง position_mstr ที่เพิ่มเติมไปอีกที

ขั้นตอนการเปลี่ยนแปลงข้อมูลแบบนี้ เราเรียกว่าการทำ Normalization ครับ ตามปกติแล้วเขาจะมีการทำราวๆ 2-4 ครั้ง ตามแต่ว่าเรียนกันมาตำราไหนเท่านั้นเอง แต่ทุกตำรามีเป้าหมายเหมือนกันก็คือ ลดการซ้ำซ้อน และความน่าจะเป็นที่จะก่อให้เกิดความผิดพลาดในการป้อนข้อมูลเข้าไปในฐานข้อมูลครับ โดยการแทนที่ด้วยเลขรหัส แล้วทำตารางเก็บรายการเอาไว้อ้างอิงต่างหาก

เป้าหมายจะอยู่ที่ ข้อมูลที่มีการกรอกเดิมๆ ซ้ำๆ ในหลายๆ ระเบียนนั่นเอง (ในที่นี้ ชื่อแผนก และชื่อตำแหน่ง มีสิทธิ์ที่จะซ้ำได้ ในระเบียนที่แตกต่างกัน)

ประเด็นที่เกิดขึ้นต่อมาก็คือ แล้วเวลาสืบค้นข้อมูลเขาจะทำกันอย่างไร?!? เพราะถ้าเกิดสืบค้นแบบ

SELECT * FROM employee

ผลที่ได้เราก็เห็นๆ อยู่แล้ว ว่าเราจะเห็นรายชื่อแผนก กับรายชื่อตำแหน่งเป็นตัวเลข 1, 2, 3,... แบบเนี้ย ซึ่งคนที่ไม่ใช่คนพัฒนาเว็บแอปพลิเคชั่นคงไม่ทราบแน่ และถึงแม้จะทราบ แต่มันก็ทำให้สับสนนะครับ ก็แหม สำหรับฟิลด์ dept_id นั้น หากมีค่าเป็น 1 จะหมายถึงแผนก Finance แต่หากเป็นฟิลด์ pos_id แล้ว ถ้ามีค่าเป็น 1 จะหมายถึงตำแหน่ง Manager... จำยุ่งยากตายชัก

ตอนหน้าเรามาดูวิธีการสืบค้นที่จะช่วยแก้ปัญหานี้ครับ คือการสืบค้นมากกว่า 1 ตารางขึ้นไปนั่นเอง

(ติดตามตอนต่อไป)

<- Back | Next ->

ThaiMisc.Com : Free Webboard | Free GuestBook | Free Poll | Free Ecard Server | Free Java Chat Room | Advertising | Contact Us
Copyright 1999-2006 Thailand Miscellaneous. Allrights reserved. webmaster@thaimisc.com