🔵 PostgreSQL

เจาะลึก PostgreSQL Constraints: การกำหนด Primary Key, SERIAL และกฎควบคุมข้อมูลให้แม่นยำ

8 นาที 17 views บันทึกเป็น PDF
เจาะลึก PostgreSQL Constraints: การกำหนด Primary Key, SERIAL และกฎควบคุมข้อมูลให้แม่นยำ

เรียนรู้วิธีคุมคุณภาพข้อมูลใน PostgreSQL ด้วย Primary Key, SERIAL, NOT NULL และ UNIQUE เพื่อป้องกันบั๊กและช่วยให้ฐานข้อมูลของคุณทำงานได้แม่นยำและเป็นระเบียบ

ทำไมต้องรู้จักการกำหนดกฎให้ข้อมูลในฐานข้อมูล

เวลาเราสร้างแอปพลิเคชัน ข้อมูลที่เก็บไว้ใน PostgreSQL (ระบบจัดการฐานข้อมูลแบบเชิงสัมพันธ์) เปรียบเสมือนสมุดบันทึกรายชื่อลูกค้า ถ้าเราปล่อยให้เขียนอะไรลงไปก็ได้ เช่น ลืมใส่ชื่อ หรือใส่เลขเบอร์โทรซ้ำกัน มั่วไปหมด ข้อมูลในระบบจะพังและใช้งานไม่ได้เลย

เราจึงต้องมี Constraints (กฎเกณฑ์ที่ใช้ควบคุมความถูกต้องของข้อมูล) เพื่อบังคับให้ข้อมูลที่กรอกเข้ามาต้องอยู่ในรูปแบบที่เรากำหนดไว้เท่านั้น นี่คือหัวใจสำคัญของการออกแบบฐานข้อมูลที่ดี ซึ่งโปรแกรมเมอร์มืออาชีพต้องให้ความสำคัญตั้งแต่เริ่มโปรเจกต์

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

รู้จักกับ Primary Key กุญแจสำคัญในการแยกแยะข้อมูล

Primary Key (กุญแจหลักที่ใช้ระบุตัวตนของข้อมูลแต่ละแถว) คือสิ่งที่บอกว่าข้อมูลชุดนี้เป็นของใครแบบไม่ซ้ำกับคนอื่น เหมือนเลขบัตรประชาชนที่ใช้แยกคนในประเทศ การตั้งค่านี้สำคัญมากเพราะถ้าไม่มีมัน เราจะหาหรือแก้ไขข้อมูลได้ยากมาก

ถ้าเราไม่มีกุญแจหลัก เวลาจะลบข้อมูลลูกค้าชื่อ "สมชาย" เราอาจจะลบผิดคนถ้ามีสมชายหลายคนในระบบ การกำหนด Primary Key จะทำให้ทุกแถวในตารางมี "ชื่อเรียก" ที่ไม่ซ้ำกันแน่นอน ทำให้การดึงข้อมูลออกมาทำได้รวดเร็วและแม่นยำ

ในการออกแบบตาราง เรามักเลือกคอลัมน์ที่เป็นค่าเฉพาะตัวมาทำหน้าที่นี้ แต่ถ้าไม่มีคอลัมน์ไหนเหมาะ เราก็จะสร้างคอลัมน์ใหม่ขึ้นมาเพื่อทำหน้าที่นี้โดยเฉพาะครับ

-- สร้างตารางสมาชิกโดยกำหนดให้ id เป็น Primary Key
CREATE TABLE members (
    id SERIAL PRIMARY KEY,
    name TEXT
);

อธิบายโค้ด: id คือชื่อคอลัมน์ SERIAL คือคำสั่งให้เลขรันอัตโนมัติ และ PRIMARY KEY คือการบอกว่าคอลัมน์นี้ห้ามซ้ำและห้ามว่าง ผลลัพธ์ที่ได้คือตารางชื่อ members ที่พร้อมใช้งานและมีหมายเลขประจำตัวสมาชิกให้ทันทีที่เพิ่มข้อมูล

การรันเลขอัตโนมัติด้วย SERIAL และ IDENTITY

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

ในปัจจุบัน PostgreSQL แนะนำให้ใช้คำสั่ง GENERATED ALWAYS AS IDENTITY แทน SERIAL เพราะเป็นมาตรฐานสากลและใช้งานได้ปลอดภัยกว่า แต่ทั้งสองแบบก็มีจุดประสงค์เดียวกันคือ การรันเลขให้เราโดยอัตโนมัติเพื่อใช้เป็นตัวระบุตัวตน

คุณแค่เลือกใช้ตามความเหมาะสมของโปรเจกต์ แต่ถ้าถามว่าตัวไหนทันสมัยกว่า ก็ต้องยกให้ IDENTITY ครับ มันจะช่วยให้โค้ดของคุณดูเป็นระเบียบและเป็นไปตามมาตรฐานที่คนทั่วโลกใช้กันในปัจจุบัน

-- วิธีการใช้ GENERATED ALWAYS AS IDENTITY
CREATE TABLE products (
    product_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    product_name TEXT
);

อธิบายโค้ด: INT คือชนิดข้อมูลตัวเลขจำนวนเต็ม GENERATED ALWAYS AS IDENTITY คือคำสั่งสั่งให้ฐานข้อมูลคอยเพิ่มเลขให้เองทุกครั้งที่เพิ่มสินค้า ผลลัพธ์คือคุณสามารถเพิ่มข้อมูลสินค้าได้โดยไม่ต้องสนใจเลขไอดี ระบบจะใส่เลข 1, 2, 3 ไปเรื่อยๆ ให้เอง

บังคับใส่ข้อมูลด้วย NOT NULL

บางครั้งเรามีคอลัมน์ที่จำเป็นต้องมีข้อมูลเสมอ เช่น ชื่อลูกค้า หรืออีเมล ถ้าปล่อยให้ว่างเปล่า ระบบอาจจะทำงานผิดพลาดได้ NOT NULL (ข้อกำหนดที่ห้ามให้ช่องนั้นว่างเปล่า) จึงเป็นตัวช่วยป้องกันความผิดพลาดในจุดนี้

ลองนึกภาพว่าเราทำแอปขายของออนไลน์ แต่ลูกค้าสั่งซื้อโดยไม่ใส่อีเมลไว้ติดต่อกลับ แบบนี้จะเกิดปัญหาตอนส่งของแน่นอน การใช้ NOT NULL จะช่วยให้ฐานข้อมูลปฏิเสธการบันทึกทันทีถ้าเราลืมกรอกข้อมูลที่จำเป็นลงไป

การกำหนดค่านี้ตั้งแต่ตอนสร้างตารางจะช่วยประหยัดเวลาในการเขียนโค้ดเช็คข้อมูลฝั่งโปรแกรม (ฝั่งที่ติดต่อกับผู้ใช้) ได้เยอะมาก เพราะเรามั่นใจได้เลยว่าข้อมูลในฐานข้อมูลของเราจะมีครบถ้วนตามที่ต้องการครับ

-- กำหนดให้ username ห้ามเป็นค่าว่าง
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username TEXT NOT NULL
);

อธิบายโค้ด: NOT NULL วางไว้หลังชนิดข้อมูล TEXT เพื่อบอกว่าคอลัมน์ username ต้องมีค่าเสมอ ผลลัพธ์คือถ้าคุณพยายามเพิ่มข้อมูลโดยไม่ใส่ชื่อผู้ใช้ ฐานข้อมูลจะส่งข้อความเตือนกลับมาว่า null value in column "username" violates not-null constraint ทันที

ป้องกันข้อมูลซ้ำด้วย UNIQUE

ในบางกรณีเราต้องการให้ข้อมูลไม่ซ้ำกัน แต่ไม่ต้องการใช้เป็น Primary Key เช่น อีเมล หรือ เบอร์โทรศัพท์ ที่แต่ละคนต้องมีหนึ่งเดียวในระบบ UNIQUE (กฎที่บังคับว่าห้ามมีข้อมูลซ้ำกันในคอลัมน์นั้น) คือคำตอบของปัญหานี้

ถ้าเราไม่กำหนด UNIQUE ไว้ คนหนึ่งคนอาจจะสมัครสมาชิกด้วยอีเมลเดิมซ้ำได้ถึงสิบครั้ง ซึ่งจะทำให้ระบบเรายุ่งเหยิงและจัดการข้อมูลลำบากมาก การสั่งห้ามซ้ำตั้งแต่ระดับฐานข้อมูลถือเป็นการป้องกันที่ต้นเหตุที่ดีที่สุด

มือใหม่มักลืมใส่ตรงนี้และไปแก้ปัญหาด้วยการเขียนโค้ดเช็คในภาษาโปรแกรม ซึ่งอาจจะพลาดได้ง่ายกว่ามาก การให้ฐานข้อมูลเป็นคนคุมกฎนี้จึงเป็นวิธีที่โปรแกรมเมอร์มืออาชีพเลือกใช้ครับ

-- กำหนดให้ email ห้ามซ้ำกัน
CREATE TABLE members (
    id SERIAL PRIMARY KEY,
    email TEXT UNIQUE
);

อธิบายโค้ด: คำว่า UNIQUE จะเข้าไปควบคุมคอลัมน์ email ผลลัพธ์คือถ้ามีใครพยายามสมัครด้วยอีเมลที่เคยมีคนใช้ไปแล้ว ฐานข้อมูลจะหยุดการทำงานและแจ้งเตือนว่า duplicate key value violates unique constraint ทำให้ข้อมูลในระบบสะอาดและไม่ซ้ำซ้อน

คุมขอบเขตข้อมูลด้วย CHECK Constraints

บางครั้งข้อมูลก็ต้องมีเงื่อนไขพิเศษ เช่น อายุต้องมากกว่า 18 ปี หรือ ราคาสินค้าต้องไม่ติดลบ CHECK (กฎที่ใช้ตรวจสอบเงื่อนไขเฉพาะ) ช่วยให้เราเขียนเงื่อนไขทางคณิตศาสตร์หรือตรรกะง่ายๆ ลงไปในฐานข้อมูลได้เลย

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

นี่คือตัวอย่างของการเขียนโปรแกรมเชิงป้องกัน (Preventive Programming) ที่ทำให้ซอฟต์แวร์ของคุณแข็งแกร่ง ไม่ว่าจะเจอผู้ใช้งานกรอกข้อมูลมาแบบไหน คุณก็มั่นใจได้ว่าข้อมูลในฐานข้อมูลจะถูกต้องตามกฎที่คุณวางไว้

-- เช็คว่าราคาต้องมากกว่า 0 เสมอ
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    price NUMERIC CHECK (price > 0)
);

อธิบายโค้ด: CHECK (price > 0) เป็นการตั้งเงื่อนไขว่าค่าใน price ต้องมากกว่า 0 เท่านั้น ผลลัพธ์คือถ้าคุณพยายามใส่ราคาเป็น 0 หรือติดลบ ฐานข้อมูลจะปฏิเสธรายการนั้นทันทีและแสดงข้อความ new row for relation violates check constraint

สรุป: เอาไปใช้จริงในโปรเจกต์แรกของคุณ

การออกแบบฐานข้อมูลที่ดีคือจุดเริ่มต้นของโปรแกรมเมอร์ที่เก่ง เมื่อคุณเริ่มทำโปรเจกต์แรก เช่น แอปสมุดจดบันทึก ให้เริ่มจากคิดว่าอะไรคือสิ่งที่ห้ามซ้ำ อะไรคือสิ่งที่ห้ามว่าง และอะไรคือเงื่อนไขพิเศษของข้อมูลนั้นๆ

ลองนำสิ่งที่เรียนวันนี้ไปใช้ โดยเริ่มจากสร้างตาราง tasks (งานที่ต้องทำ) ให้มี id เป็น PRIMARY KEY, title เป็น NOT NULL, และอาจมีคอลัมน์ priority ที่ใช้ CHECK เพื่อกำหนดว่าต้องเป็นเลข 1 ถึง 5 เท่านั้น

อย่าลืมว่าการทำฐานข้อมูลให้แน่นหนาตั้งแต่แรก จะช่วยให้คุณประหยัดเวลาแก้บั๊กในอนาคตได้มหาศาล ขอให้สนุกกับการเขียนโค้ดและสร้างสรรค์โปรเจกต์ของคุณให้เต็มที่ครับ!

แชร์บทความ

Facebook X LINE

บทความที่เกี่ยวข้อง

จัดการ PostgreSQL เบื้องต้น: การคุมสิทธิ์ User, การ Backup และ Restore ข้อมูลบน Windows
PostgreSQL

จัดการ PostgreSQL เบื้องต้น: การคุมสิทธิ์ User, การ Backup และ Restore ข้อมูลบน Windows

มือใหม่ต้องรู้! วิธีจัดการสิทธิ์ผู้ใช้งาน (Role) และการสำรองข้อมูล (Backup) ใน PostgreSQL ให้ปลอดภัย พร้อมวิธี Restore ข้อมูลกลับมาใช้ได้จริงผ่าน Command Line

4 weeks ago 8 นาที
26 views
เจาะลึก PostgreSQL Triggers: วิธีเขียนคำสั่งทำงานอัตโนมัติเมื่อข้อมูลเปลี่ยน
PostgreSQL

เจาะลึก PostgreSQL Triggers: วิธีเขียนคำสั่งทำงานอัตโนมัติเมื่อข้อมูลเปลี่ยน

อยากให้ฐานข้อมูลทำงานอัตโนมัติเมื่อมีการเพิ่มหรือแก้ไขข้อมูลไหม? มาเรียนรู้การใช้ PostgreSQL Triggers (ตัวสั่งการอัตโนมัติ) ทั้ง BEFORE และ AFTER เพื่อลดงานซ้ำซ้อน

4 weeks ago 8 นาที
20 views
เจาะลึก PostgreSQL PL/pgSQL: เขียนฟังก์ชันและ Stored Procedures ฉบับมือใหม่
PostgreSQL

เจาะลึก PostgreSQL PL/pgSQL: เขียนฟังก์ชันและ Stored Procedures ฉบับมือใหม่

เรียนรู้วิธีเขียนโปรแกรมในฐานข้อมูลด้วย PL/pgSQL ทั้งการสร้างฟังก์ชัน การใช้ตัวแปร และการทำ Loop เพื่อให้งานจัดการข้อมูลของคุณเร็วและเป็นระเบียบยิ่งขึ้น

4 weeks ago 8 นาที
19 views