🔵 PostgreSQL

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

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

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

PL/pgSQL คืออะไรและทำไมต้องรู้จัก

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

PL/pgSQL (ภาษาที่ใช้เขียนโปรแกรมภายในฐานข้อมูล PostgreSQL) จึงเข้ามาแก้ปัญหานี้ โดยมันยอมให้เราเขียน "สคริปต์" (ชุดคำสั่งที่รันตามลำดับ) เก็บไว้ในฐานข้อมูลเลย เหมือนกับการสอนฐานข้อมูลให้รู้จักทำภารกิจเองโดยที่เราไม่ต้องคอยสั่ง

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

การสร้างฟังก์ชันเบื้องต้นด้วย CREATE FUNCTION

การ CREATE FUNCTION (คำสั่งสร้างฟังก์ชัน) คือการสอนให้ฐานข้อมูลทำงานบางอย่างแล้วส่งค่ากลับมาให้เราเหมือนการคำนวณเลข หรือการดึงค่าบางอย่างออกมาใช้ ฟังก์ชันใน PostgreSQL ต้องระบุประเภทของข้อมูลที่จะรับเข้ามาและประเภทข้อมูลที่จะส่งกลับไปเสมอ

เราต้องใช้คำสั่ง LANGUAGE plpgsql เพื่อบอกฐานข้อมูลว่าเรากำลังเขียนด้วยภาษานี้ และต้องครอบโค้ดด้วย $$ เพื่อบอกจุดเริ่มต้นและจุดจบของคำสั่งทั้งหมด Block (กลุ่มของคำสั่งที่ทำงานร่วมกัน) จะเริ่มต้นด้วย BEGIN และจบด้วย END เสมอ

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

-- สร้างฟังก์ชันบวกเลขง่ายๆ
CREATE FUNCTION add_numbers(a integer, b integer)
RETURNS integer AS $$
BEGIN
    RETURN a + b;
END;
$$ LANGUAGE plpgsql;

อธิบายโค้ด:

  • CREATE FUNCTION add_numbers คือการตั้งชื่อฟังก์ชันว่า add_numbers
  • (a integer, b integer) คือการกำหนดตัวแปรที่จะรับเข้ามา 2 ตัว โดยต้องเป็นตัวเลขจำนวนเต็มทั้งคู่
  • RETURNS integer คือการบอกว่าผลลัพธ์ที่ได้จะเป็นตัวเลขจำนวนเต็ม
  • BEGIN ... END คือส่วนที่บรรจุคำสั่งหลักของเรา
  • RETURN a + b คือการสั่งให้เอาค่า a มาบวกกับค่า b แล้วส่งผลลัพธ์ออกมา

ผลลัพธ์: เมื่อรันคำสั่ง SELECT add_numbers(5, 10); ฐานข้อมูลจะตอบกลับมาว่า 15

การใช้ตัวแปรและการกำหนดค่า

ใน PL/pgSQL เราสามารถประกาศ DECLARE (การจองพื้นที่ในหน่วยความจำเพื่อเก็บข้อมูล) เพื่อเอาไว้พักข้อมูลระหว่างคำนวณได้ ตัวแปรเหล่านี้ช่วยให้เราเขียนโค้ดที่ซับซ้อนขึ้นได้โดยไม่ต้องเขียนคำสั่งยาว ๆ ในบรรทัดเดียว

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

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

-- การใช้ตัวแปรพักข้อมูล
CREATE FUNCTION get_discount(price integer)
RETURNS integer AS $$
DECLARE
    discount integer := 10; -- ประกาศตัวแปรลดราคา
BEGIN
    RETURN price - discount;
END;
$$ LANGUAGE plpgsql;

อธิบายโค้ด:

  • DECLARE คือส่วนที่ประกาศตัวแปรทั้งหมดที่จะใช้ในฟังก์ชันนี้
  • discount integer := 10 คือการสร้างกล่องชื่อ discount เก็บเลข 10 ไว้
  • price - discount คือการนำค่าที่รับเข้ามาลบด้วยค่าในกล่อง discount

ผลลัพธ์: เมื่อรัน SELECT get_discount(100); ผลลัพธ์ที่ได้คือ 90

การควบคุม Loop เพื่อทำงานซ้ำ

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

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

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

-- ตัวอย่างการวนซ้ำเพื่อแสดงข้อความ
CREATE FUNCTION show_numbers()
RETURNS void AS $$
BEGIN
    FOR i IN 1..3 LOOP
        RAISE NOTICE 'เลขที่: %', i;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

อธิบายโค้ด:

  • FOR i IN 1..3 คือการบอกให้เริ่มนับตั้งแต่ 1 ถึง 3
  • RAISE NOTICE คือคำสั่งให้ฐานข้อมูลแสดงข้อความออกมาที่หน้าจอ
  • % คือสัญลักษณ์ที่จะนำค่าของตัวแปร i มาใส่แทนที่

ผลลัพธ์: ในหน้าต่างข้อความของโปรแกรมจัดการฐานข้อมูล จะเห็นข้อความขึ้นว่า เลขที่: 1, เลขที่: 2, และ เลขที่: 3

รู้จัก Stored Procedures ใน PostgreSQL

CREATE PROCEDURE (คำสั่งสร้างกระบวนการทำงาน) คล้ายกับฟังก์ชัน แต่มีความต่างสำคัญคือมันไม่จำเป็นต้องส่งค่ากลับ (ไม่ใช้ RETURNS) และมันสามารถควบคุม Transaction (การบันทึกข้อมูลแบบเป็นชุดที่ต้องสำเร็จทั้งหมดหรือล้มเหลวทั้งหมด) ได้ด้วยตัวเอง

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

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

-- ตัวอย่างการสร้าง Procedure
CREATE PROCEDURE update_data()
LANGUAGE plpgsql
AS $$
BEGIN
    UPDATE users SET status = 'active';
    -- ทำการเปลี่ยนสถานะผู้ใช้ทุกคนให้เป็น active
END;
$$;

อธิบายโค้ด:

  • CREATE PROCEDURE คือการสร้างชุดคำสั่งที่เน้นการจัดการข้อมูล
  • UPDATE users คือคำสั่งแก้ไขข้อมูลในตาราง users
  • ไม่มี RETURNS เพราะ Procedure เน้นการทำงาน ไม่เน้นการส่งค่ากลับ

ผลลัพธ์: เมื่อเรียกใช้ด้วย CALL update_data(); ข้อมูลในตาราง users ทั้งหมดจะถูกเปลี่ยนสถานะทันที

สรุป: การนำไปใช้จริงในงานโปรแกรมเมอร์

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

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

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

แชร์บทความ

Facebook X LINE

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

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

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

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

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

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

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

4 weeks ago 8 นาที
20 views