ทำความรู้จักการเพิ่มข้อมูลด้วย INSERT INTO
เวลาเราสร้างแอปพลิเคชัน ข้อมูลที่ผู้ใช้กรอกเข้ามาจะถูกเก็บไว้ในฐานข้อมูล การเพิ่มข้อมูลใหม่เข้าไปในตารางเรียกว่าการทำ INSERT INTO (คำสั่งเพิ่มข้อมูลลงในตาราง) เปรียบเหมือนการเขียนชื่อเพื่อนลงในสมุดรายชื่อ ถ้าเราไม่มีคำสั่งนี้ เราก็ไม่สามารถบันทึกอะไรลงในฐานข้อมูลได้เลย
ก่อนจะเริ่มเขียนโค้ด เราต้องมีตารางสำหรับเก็บข้อมูลก่อน สมมติว่าเราทำระบบสมาชิกที่ต้องเก็บชื่อและอีเมล ทุกครั้งที่มีคนสมัครสมาชิกใหม่ เราจะใช้คำสั่งนี้เพื่อบันทึกข้อมูลลงไปใน Table (ตารางเก็บข้อมูลที่แบ่งเป็นแถวและคอลัมน์) โดยอ้างอิงชื่อคอลัมน์ที่เราออกแบบไว้
การเข้าใจคำสั่งนี้เป็นก้าวแรกที่สำคัญมากของโปรแกรมเมอร์มือใหม่ เพราะมันคือพื้นฐานของการจัดการข้อมูลทั้งหมด หากคุณเขียนคำสั่งนี้ผิดพลาด ข้อมูลสำคัญของลูกค้าอาจจะหายไปหรือไม่ถูกบันทึกเลย ดังนั้นเรามาดูโครงสร้างคำสั่งที่ถูกต้องกัน
-- เพิ่มข้อมูลสมาชิกใหม่ 1 คน
INSERT INTO users (name, email)
VALUES ('Somchai', 'somchai@example.com');
คำสั่งข้างต้นประกอบด้วย INSERT INTO เพื่อระบุชื่อตาราง users ตามด้วยชื่อคอลัมน์ในวงเล็บ และ VALUES เพื่อระบุค่าที่จะใส่ลงไปตามลำดับคอลัมน์ที่กำหนดไว้
ผลลัพธ์ที่ควรเห็นคือข้อความแจ้งเตือนจากฐานข้อมูลว่า INSERT 0 1 ซึ่งหมายความว่ามีการเพิ่มข้อมูลสำเร็จจำนวน 1 แถวในตารางเรียบร้อยแล้ว
การทำ Bulk Insert เพื่อความรวดเร็ว
ในชีวิตจริงเรามักไม่ได้เพิ่มข้อมูลทีละคน แต่บางครั้งต้องนำเข้าข้อมูลจำนวนมากพร้อมกัน การทำ Bulk Insert (การเพิ่มข้อมูลหลายแถวในคำสั่งเดียว) จะช่วยประหยัดเวลาและลดภาระของฐานข้อมูลได้ดีกว่าการสั่งเพิ่มทีละครั้งเปรียบเหมือนการเขียนชื่อเพื่อน 10 คนในบรรทัดเดียวแทนที่จะเขียนทีละบรรทัด
การเขียนแบบนี้ช่วยลดจำนวนการเชื่อมต่อระหว่างโปรแกรมของเรากับฐานข้อมูล ทำให้แอปพลิเคชันทำงานได้เร็วขึ้นมาก โดยเฉพาะในขั้นตอนการ Migrate (การย้ายหรืออัปเดตโครงสร้างฐานข้อมูล) หรือการนำเข้าข้อมูลเริ่มต้นของระบบใหม่
มือใหม่มักพลาดโดยการเขียนคำสั่งวนลูปในโค้ดเพื่อสั่งเพิ่มข้อมูลทีละบรรทัด ซึ่งเป็นวิธีที่ไม่แนะนำเพราะมันจะทำให้ระบบช้าลงอย่างเห็นได้ชัดเมื่อข้อมูลมีจำนวนมากขึ้น การทำ Bulk Insert จึงเป็นเทคนิคที่โปรแกรมเมอร์ทุกคนต้องฝึกให้ชิน
-- เพิ่มสมาชิกหลายคนพร้อมกันในคำสั่งเดียว
INSERT INTO users (name, email)
VALUES
('Somsak', 'somsak@example.com'),
('Malee', 'malee@example.com'),
('Wichai', 'wichai@example.com');
ในโค้ดนี้เราใช้ VALUES แล้วตามด้วยข้อมูลแต่ละชุดคั่นด้วยเครื่องหมายจุลภาค , ทำให้เราสามารถเพิ่มสมาชิกได้คราวละหลายคนโดยสั่งงานเพียงครั้งเดียว
ผลลัพธ์ที่ควรเห็นคือข้อความแจ้งเตือน INSERT 0 3 ซึ่งหมายความว่าระบบได้บันทึกข้อมูลใหม่ลงไปทั้งหมด 3 แถวเรียบร้อยแล้ว
ปัญหาข้อมูลซ้ำและจุดเริ่มต้นของ UPSERT
บางครั้งเราพยายามเพิ่มข้อมูลที่มี Primary Key (รหัสประจำตัวที่ห้ามซ้ำกันเด็ดขาด) ไปซ้ำกับข้อมูลเดิมที่มีอยู่แล้ว ฐานข้อมูลจะส่งข้อความแจ้งเตือนข้อผิดพลาดออกมาทันที ทำให้โปรแกรมของเราหยุดทำงานหรือเกิดบั๊กได้ง่าย
นี่คือเหตุผลที่เราต้องรู้จัก UPSERT (การรวมคำว่า Update และ Insert เข้าด้วยกัน) มันคือเทคนิคที่บอกฐานข้อมูลว่า ถ้าข้อมูลนี้ไม่มีอยู่ให้เพิ่มใหม่ แต่ถ้ามีอยู่แล้วให้แก้ไขข้อมูลเดิมแทน เปรียบเหมือนการอัปเดตสมุดรายชื่อ ถ้ามีชื่อเพื่อนคนนี้แล้วก็แค่เปลี่ยนเบอร์โทร แต่ถ้ายังไม่มีก็ให้เขียนชื่อเพิ่มเข้าไป
การทำ UPSERT ช่วยให้โค้ดของเรามีความทนทานและไม่ต้องเขียนเงื่อนไขตรวจสอบข้อมูลซ้ำซ้อนในฝั่งโปรแกรมเมอร์ให้ยุ่งยาก เป็นแนวปฏิบัติที่ดีที่ช่วยให้การจัดการข้อมูลมีความแม่นยำและปลอดภัยในระยะยาว
-- ทดลองเพิ่มข้อมูลที่ซ้ำกับของเดิม
INSERT INTO users (name, email)
VALUES ('Somchai', 'new_email@example.com');
-- ผลคือจะเกิดข้อผิดพลาดเพราะชื่อ Somchai มีอยู่แล้ว
โค้ดนี้แสดงสถานการณ์ที่ผิดพลาดเมื่อชื่อ Somchai มีอยู่แล้วในระบบ ฐานข้อมูลจะปฏิเสธการทำงานและส่งข้อความเตือนว่า Unique Constraint Violation (การละเมิดกฎข้อมูลที่ไม่ซ้ำกัน) เพื่อป้องกันไม่ให้ข้อมูลสำคัญเสียหาย
การใช้ ON CONFLICT เพื่อทำ UPSERT
เพื่อแก้ปัญหาข้อมูลซ้ำ เราจะใช้คำสั่ง ON CONFLICT (คำสั่งจัดการกรณีข้อมูลซ้ำ) เพื่อกำหนดทิศทางว่าถ้าเกิดการชนกันของข้อมูล เราอยากให้ฐานข้อมูลทำอย่างไรต่อ นี่เป็นหัวใจสำคัญของการเขียนโค้ดจัดการฐานข้อมูลที่มืออาชีพใช้กัน
เราสามารถเลือกได้สองทางหลักคือ DO NOTHING ถ้าไม่อยากทำอะไรเลยเมื่อข้อมูลซ้ำ หรือ DO UPDATE ถ้าต้องการอัปเดตข้อมูลเก่าให้เป็นค่าใหม่แทน สิ่งนี้ช่วยให้ระบบของเราทำงานต่อเนื่องได้โดยไม่ต้องกังวลเรื่องการหยุดชะงัก
การเลือกใช้อย่างใดอย่างหนึ่งขึ้นอยู่กับความต้องการของงาน เช่น ถ้าเป็นการนำเข้าข้อมูลผู้ใช้ใหม่ เราอาจจะเลือกอัปเดตอีเมลใหม่ให้เขา แต่ถ้าเป็นการเก็บประวัติการเข้าใช้งาน เราอาจจะเลือกเมินข้อมูลที่ซ้ำไปเลยก็ได้
-- กรณีข้อมูลซ้ำ ให้เปลี่ยนอีเมลเป็นค่าใหม่
INSERT INTO users (name, email)
VALUES ('Somchai', 'new_email@example.com')
ON CONFLICT (name)
DO UPDATE SET email = EXCLUDED.email;
คำสั่ง ON CONFLICT (name) คือการระบุว่าถ้าชื่อซ้ำกันให้ทำงานต่อ DO UPDATE จะทำการแก้ไขข้อมูลในคอลัมน์ email ให้เป็นค่าใหม่ที่ส่งเข้ามา ซึ่งเราใช้คำสั่ง EXCLUDED เพื่ออ้างถึงค่าข้อมูลชุดใหม่ที่พยายามจะเพิ่มเข้าไปนั่นเอง
ผลลัพธ์ที่ได้คือข้อมูลของ Somchai จะถูกอัปเดตอีเมลใหม่โดยไม่มีข้อผิดพลาดเกิดขึ้นและไม่ต้องเขียนโค้ดตรวจสอบซ้ำซ้อน
เทคนิค DO NOTHING เมื่อเจอข้อมูลซ้ำ
บางสถานการณ์เราแค่ต้องการป้องกันไม่ให้เกิดข้อผิดพลาดเมื่อข้อมูลซ้ำโดยไม่ต้องไปแก้ไขอะไรเลย การใช้ DO NOTHING (คำสั่งให้เพิกเฉยเมื่อข้อมูลซ้ำ) จึงเป็นทางเลือกที่ง่ายและรวดเร็วที่สุดสำหรับมือใหม่
ยกตัวอย่างเช่น การบันทึกรายชื่อผู้เข้าร่วมกิจกรรม ถ้ามีคนพยายามลงทะเบียนซ้ำด้วยชื่อเดิม เราอาจจะแค่ต้องการให้ระบบข้ามคนนั้นไปเพื่อให้แน่ใจว่าแต่ละคนลงทะเบียนได้เพียงครั้งเดียวเท่านั้น ซึ่งวิธีนี้ช่วยประหยัดเวลาการเขียนโค้ดได้มหาศาล
การทำความเข้าใจความแตกต่างระหว่างการอัปเดตข้อมูลกับการเพิกเฉย จะช่วยให้คุณออกแบบตรรกะของแอปพลิเคชันได้ยืดหยุ่นขึ้นมาก ลองฝึกใช้ทั้งสองคำสั่งนี้กับโปรเจกต์เล็กๆ ของคุณดู แล้วคุณจะพบว่ามันช่วยลดงานแก้บั๊กไปได้เยอะเลย
-- ถ้าชื่อซ้ำ ให้ข้ามไปเลยไม่ต้องทำอะไร
INSERT INTO users (name, email)
VALUES ('Somchai', 'another_email@example.com')
ON CONFLICT (name)
DO NOTHING;
คำสั่งนี้จะตรวจสอบว่าชื่อ Somchai มีอยู่แล้วหรือไม่ ถ้ามีอยู่แล้วคำสั่ง DO NOTHING จะสั่งให้ฐานข้อมูลไม่ต้องบันทึกอะไรใหม่และไม่ต้องแก้ไขข้อมูลเดิม ทำให้ระบบยังคงทำงานต่อไปได้โดยไม่มีข้อผิดพลาด
ผลลัพธ์คือไม่มีข้อมูลใหม่ถูกเพิ่มเข้ามาและไม่มีข้อความเตือนข้อผิดพลาดปรากฏขึ้น ระบบจะทำงานเงียบๆ เหมือนไม่มีอะไรเกิดขึ้น
สรุป: นำไปใช้จริงให้โปรเจกต์ราบรื่น
การจัดการข้อมูลด้วย INSERT และ UPSERT เป็นทักษะพื้นฐานที่โปรแกรมเมอร์ทุกคนต้องคล่องแคล่ว ไม่ว่าคุณจะทำแอปอะไร การบันทึกข้อมูลที่ถูกต้องและมีประสิทธิภาพคือหัวใจหลักที่ทำให้แอปของคุณน่าเชื่อถือและทำงานได้ไม่สะดุด
สมมติว่าคุณกำลังสร้างระบบจัดการคลังสินค้า เมื่อมีสินค้าเข้ามาใหม่คุณต้องเพิ่มข้อมูลลงฐานข้อมูล ถ้ามีการสแกนบาร์โค้ดสินค้าเดิมซ้ำ คุณสามารถใช้ ON CONFLICT เพื่ออัปเดตจำนวนสินค้าคงเหลือได้โดยอัตโนมัติ ซึ่งช่วยให้พนักงานไม่ต้องมานั่งแก้ไขข้อมูลเองด้วยมือ
ขอให้จำไว้ว่า การเขียนโค้ดที่ดีเริ่มจากการเข้าใจเครื่องมือที่มีในมือ อย่ากลัวที่จะลองผิดลองถูกกับฐานข้อมูลจำลองในเครื่องตัวเองก่อนนำไปใช้จริง ฝึกฝนบ่อยๆ แล้วคุณจะกลายเป็นโปรแกรมเมอร์ที่สามารถจัดการข้อมูลได้อย่างมืออาชีพแน่นอนครับ