PlusMagi's Blog By Pitt Phunsanit Backend,Database Stored Procedures vs User-Defined Functions (UDF): เมื่อไหร่ควรใช้ และข้อควรระวังในการเขียน Business Logic บน DB

Stored Procedures vs User-Defined Functions (UDF): เมื่อไหร่ควรใช้ และข้อควรระวังในการเขียน Business Logic บน DB

ในฐานะสถาปนิกระบบ (System Architect) การจัดการ ‘กฎทางธุรกิจ’ (Business Logic) ให้มีความสอดคล้องและปลอดภัยถือเป็นหัวใจสำคัญของการพัฒนาซอฟต์แวร์ที่เชื่อถือได้ หากเราปล่อยให้ตรรกะเหล่านี้กระจัดกระจายอยู่ตามแอปพลิเคชันหลายส่วน ความเสี่ยงของข้อมูลไม่สม่ำเสมอ (Data Inconsistency) จะสูงขึ้นตามไปด้วย การตัดสินใจว่าจะเก็บ Logic เหล่านี้ไว้ที่ชั้นแอปพลิเคชัน (Application Layer) หรือชั้นฐานข้อมูล (Database Layer) จึงเป็นเรื่องที่วิศวกรทุกคนต้องให้ความสำคัญ

Stored Procedures (SP) vs User-Defined Functions (UDF) ใน PostgreSQL

เมื่อพูดถึงการย้าย Business Logic ลงไปอยู่ในฐานข้อมูล PostgreSQL เราจะพิจารณาเครื่องมือหลักสองตัวคือ Stored Procedures (SPs) และ User-Defined Functions (UDFs) แม้ว่าทั้งคู่จะถูกใช้เพื่อรันโค้ด SQL ที่ซับซ้อน แต่บทบาทและขีดความสามารถของมันแตกต่างกันอย่างสิ้นเชิง

🎯 บทบาทและความแตกต่างหลัก

  • User-Defined Functions (UDFs): ถูกออกแบบมาเพื่อเป็นฟังก์ชันคำนวณทางคณิตศาสตร์หรือตรรกะที่รับค่า Input และส่งค่า Output กลับ (Return Value) เท่านั้น UDFs เหมาะสำหรับการคำนวณค่าเดียว เช่น การคำนวณภาษี หรือการจัดรูปแบบข้อมูล และไม่สามารถทำการเปลี่ยนแปลงสถานะของข้อมูล (Data Modification/Transaction) ได้โดยตรง
  • Stored Procedures (SPs): ถูกออกแบบมาเพื่อจัดการชุดคำสั่งที่ซับซ้อนและเกี่ยวข้องกับการเปลี่ยนแปลงสถานะของข้อมูล (DML) SPs สามารถรับค่า Input, ประมวลผลหลายขั้นตอน, และที่สำคัญที่สุดคือสามารถควบคุม Transaction ได้อย่างสมบูรณ์ (BEGIN/COMMIT/ROLLBACK)

⚙️ กรณีศึกษาการใช้งานด้วย PostgreSQL

✅ เมื่อไหร่ที่ควรใช้ UDFs (Calculation/Read-Only)

ใช้เมื่อคุณต้องการคำนวณค่าใดค่าหนึ่งจากข้อมูลที่ป้อนเข้าไป โดยไม่ต้องการให้มีการเปลี่ยนแปลงข้อมูลในตารางหลัก ตัวอย่างเช่น การคำนวณราคาสุทธิหลังหักส่วนลด

SQL

-- ตัวอย่าง UDF: คำนวณราคาสุทธิ (Returns a single value) 
CREATE OR REPLACE FUNCTION calculate_net_price(price numeric, discount numeric) 
RETURNS numeric AS $$ 
BEGIN 
    RETURN price * (1 - discount / 100.0);
END; 
$$ LANGUAGE plpgsql; 

SELECT calculate_net_price(100.0, 10); -- ผลลัพธ์: 90.0

🚀 เมื่อไหร่ที่ควรใช้ Stored Procedures (Transaction/Modification)

ใช้เมื่อกระบวนการทางธุรกิจนั้นเป็นแบบ End-to-End และต้องมีการอัปเดตข้อมูลหลายตารางพร้อมกันเพื่อให้มั่นใจว่าข้อมูลมีความสอดคล้อง (Transactional Integrity) ตัวอย่างเช่น การโอนเงินที่ต้องลดเงินจากบัญชี A และเพิ่มเงินในบัญชี B

SQL

-- ตัวอย่าง SP: โอนเงิน (Requires transaction control) 
CREATE OR REPLACE PROCEDURE transfer_funds(sender_id int, receiver_id int, amount numeric) 
LANGUAGE plpgsql AS $$
BEGIN
    UPDATE accounts SET balance = balance - amount WHERE user_id = sender_id;
    UPDATE accounts SET balance = balance + amount WHERE user_id = receiver_id;
    COMMIT;
END;$$

CALL transfer_funds(1, 2, 50.0);

⚠️ ข้อควรระวังจากมุมมองของ Senior Architect

  1. Performance: การเรียกใช้ Logic ที่ซับซ้อนมากเกินไปใน DB อาจทำให้เกิดปัญหา Performance Bottleneck ได้ ควรพิจารณาการทำ Caching ที่ Application Layer ร่วมด้วย
  2. Security: การให้สิทธิ์ (Permissions) ในการรัน SPs ต้องจำกัดอย่างเคร่งครัด เพื่อป้องกันการเข้าถึงหรือแก้ไขข้อมูลที่เกินขอบเขตที่จำเป็น (Principle of Least Privilege)
  3. Complexity: หาก Business Logic มีความซับซ้อนสูงมากและต้องมีการจัดการ UI/UX ที่ซับซ้อน การเก็บ Logic ไว้ที่ Application Layer (เช่น Microservices) อาจยืดหยุ่นกว่า

บทสรุป: การตัดสินใจที่ถูกต้อง

โดยสรุปแล้ว หากงานของคุณคือการคำนวณ ให้ใช้ UDFs แต่ถ้างานของคุณคือการเปลี่ยนแปลงสถานะข้อมูลที่ต้องมีการรับประกันความถูกต้องของ Transaction ให้ใช้ Stored Procedures เสมอ การเข้าใจความแตกต่างนี้จะช่วยให้คุณออกแบบระบบที่มีความเสถียร ปลอดภัย และมีประสิทธิภาพสูงตามมาตรฐานของสถาปนิกซอฟต์แวร์มืออาชีพ

Exit mobile version