ในการพัฒนาระบบฐานข้อมูล (Database Development) บ่อยครั้งที่เราจำเป็นต้องรีเซ็ตสภาพแวดล้อมการทำงานทั้งหมด เพื่อให้แน่ใจว่าโค้ดที่กำลังทดสอบนั้นสะอาด ไม่มีข้อมูลเก่ามาปะปน ซึ่งกระบวนการนี้เรียกว่าการ ‘ล้างข้อมูล’ หรือ ‘Reset Database’
สำหรับผู้ที่ใช้ SQL Server อาจคุ้นเคยกับการวนลูปคำสั่ง แต่เมื่อเราเปลี่ยนมาใช้ PostgreSQL เราจำเป็นต้องใช้วิธีการที่ทรงพลังและยืดหยุ่นกว่า นั่นคือการสร้าง Dynamic SQL เพื่อจัดการกับตารางทั้งหมดใน Schema ที่ต้องการได้อย่างมีประสิทธิภาพ
💡 ทำไมต้อง Truncate แทน Delete?
ก่อนที่เราจะลงมือล้างข้อมูล เราควรทำความเข้าใจความแตกต่างระหว่างคำสั่ง DELETE FROM และ TRUNCATE TABLE ก่อน:
DELETE FROM table_name;: จะทำการลบแถว (Row) ทีละรายการ ทำให้ใช้ทรัพยากรสูงกว่าและช้ากว่า นอกจากนี้ยังคงบันทึก Log การทำธุรกรรมไว้TRUNCATE TABLE table_name;: เป็นคำสั่งที่ถูกออกแบบมาเพื่อล้างข้อมูลทั้งหมดในตารางอย่างรวดเร็วที่สุด (Fastest way to empty a table) และที่สำคัญคือ มันจะรีเซ็ต Sequence/Identity Column ให้กลับไปเริ่มต้นที่ 1 เสมอ ซึ่งเหมาะกับการทำ Development Environment มากกว่า
⚙️ การล้างข้อมูลทุกตารางใน PostgreSQL ด้วย Dynamic SQL
เนื่องจาก PostgreSQL ไม่มีคำสั่งสำเร็จรูปในการวนลูปและรัน TRUNCATE ทุกตารางโดยอัตโนมัติ เราจึงต้องใช้เทคนิคการ Query ข้อมูล Metadata (Schema) และสร้างชุดคำสั่ง SQL แบบไดนามิก (Dynamic SQL) ขึ้นมาเอง
เราจะดึงรายชื่อตารางทั้งหมดจาก information_schema.tables แล้วนำชื่อเหล่านั้นมาประกอบเป็นคำสั่ง TRUNCATE TABLE table_name CASCADE; โดยการใช้ฟังก์ชันของ PostgreSQL เช่น string_agg() และ format()
ตัวอย่างโค้ด: การสร้างชุดคำสั่ง Truncate ทั้งหมด
โค้ดนี้จะรวบรวมชื่อตารางทั้งหมดใน Schema ปัจจุบัน (public) แล้วสร้างเป็นสตริงของคำสั่ง TRUNCATE TABLE ... ที่พร้อมใช้งาน:
SQL
SELECT string_agg(format('TRUNCATE TABLE %I CASCADE;', table_name), ';
') AS truncate_commands FROM information_schema.tables WHERE table_schema = current_schema() AND table_type = 'BASE TABLE';
คำอธิบายโค้ด:
information_schema.tables: คือแหล่งข้อมูลที่เก็บ Metadata ของฐานข้อมูลWHERE table_schema = current_schema(): จำกัดขอบเขตให้เหลือเฉพาะ Schema ปัจจุบัน (เช่น ‘public’) เพื่อป้องกันการลบตารางจาก Schema อื่นโดยไม่ตั้งใจstring_agg(..., ';\n'): ทำหน้าที่รวมชื่อตารางทั้งหมดที่ได้มา ให้กลายเป็นข้อความยาวๆ ที่มีคำสั่งTRUNCATE TABLE ...;คั่นอยู่
⚠️ ข้อควรระวังและขั้นตอนการใช้งาน (Best Practice)
เนื่องจากการรัน Dynamic SQL นี้เป็นการดำเนินการที่มีผลกระทบสูงต่อข้อมูลทั้งหมดในฐานข้อมูล จึงต้องทำด้วยความระมัดระวังสูงสุดเสมอ:
- ใช้ Transaction Block: ควรห่อคำสั่งทั้งหมดไว้ใน
BEGIN; ... COMMIT;เพื่อให้สามารถ Rollback ได้หากเกิดข้อผิดพลาด - ทดสอบบน Staging Environment เท่านั้น: ห้ามรันโค้ดนี้กับ Production Database โดยเด็ดขาด
- การใช้ CASCADE: การเพิ่มคำว่า
CASCADEหลังชื่อตาราง (เช่นTRUNCATE TABLE table_name CASCADE;) มีความสำคัญมาก เพราะมันจะล้างข้อมูลในตารางที่ถูกอ้างอิง (Foreign Key) ไปยังตารางหลักโดยอัตโนมัติ ทำให้การรีเซ็ตฐานข้อมูลสมบูรณ์ยิ่งขึ้น
✅ สรุป
การใช้ Dynamic SQL ร่วมกับ information_schema เป็นวิธีมาตรฐานและมีประสิทธิภาพที่สุดในการล้างข้อมูลทั้งหมดใน PostgreSQL เพื่อให้แน่ใจว่าสภาพแวดล้อมการพัฒนาของคุณสะอาดพร้อมสำหรับการทดสอบครั้งใหม่เสมอ เพียงจำไว้ว่าความเร็วและความปลอดภัยต้องมาก่อนเสมอเมื่อจัดการกับโครงสร้างฐานข้อมูลขนาดใหญ่