MySQL: แทรก id ที่ว่างอยู่MySQL: แทรก id ที่ว่างอยู่

การใช้ CTE ร่วมกับฐานข้อมูล MySQL เพื่อหา “ช่องว่าง” ของ ID และทำการ INSERT ข้อมูลเข้าไปในตำแหน่งที่ว่างเหล่านั้น สามารถทำได้โดยสร้างลำดับตัวเลข ขึ้นมาเปรียบเทียบครับ นี่คือ SQL Script สำหรับการค้นหา ID ที่ว่างในช่วง 1 – 11713 และนำข้อมูลที่คุณต้องการใส่เข้าไปในช่องว่างเหล่านั้น


เทคนิคการใช้ Recursive CTE เพื่อเติม ID ที่ว่างใน WordPress

บ่อยครั้งที่ตาราง wp_posts ของเรามีเลข ID ที่ไม่ต่อเนื่องกัน ซึ่งอาจเกิดจากการลบโพสต์เก่า หรือการสำรองข้อมูลที่ไม่สมบูรณ์ หากเราต้องการจัดการให้ ID ตั้งแต่ 1 ถึง 11713 มีข้อมูลครบทุกแถว เราสามารถใช้ SQL ชุดนี้จัดการได้ครับ


การขยายขีดจำกัดการทำงาน

SET SESSION max_recursive_iterations = 12000;

โดยปกติ MariaDB จะจำกัดการวนลูป ไว้เพียง 1,000 รอบ เพื่อป้องกันปัญหาวนลูปไม่สิ้นสุด แต่ในโจทย์นี้เราต้องการสร้างตัวเลขสูงถึง 11,713 เราจึงต้องขยายเพดานบินให้สูงขึ้นเป็น 12,000 เพื่อให้ Query ทำงานจนจบกระบวนการ


โครงสร้างคำสั่งและการทำงาน

คำสั่งนี้แบ่งการทำงานออกเป็น 3 ส่วนหลัก ดังนี้ครับ


การสร้างลำดับตัวเลข

WITH RECURSIVE id_sequence AS 

ส่วนนี้จะสร้าง “ตารางเสมือน” ชื่อว่า id_sequence ที่มี Column n บรรจุเลข 1, 2, 3… ไปจนถึง 11,713 เตรียมไว้ในหน่วยความจำ


การเปรียบเทียบหา “ช่องว่าง”

FROM id_sequence s
LEFT JOIN `wp_posts` t ON s.n = t.ID
WHERE t.ID IS NULL;

เรานำตารางตัวเลขที่สร้างขึ้นไปวางทาบกับตาราง wp_posts จริง ๆ ด้วย LEFT JOIN และใช้เงื่อนไข WHERE t.ID IS NULL เพื่อเลือกเฉพาะ เลข ID ที่ยังไม่มีอยู่ในระบบ เท่านั้น


การแทรกข้อมูล

เมื่อได้เลข ID ที่ว่างแล้ว ระบบจะทำการ INSERT ข้อมูลที่กำหนดลงไป โดยมีไฮไลท์สำคัญคือ

  • ID: ใช้ค่า s.n มาเป็น Primary Key ใหม่
  • post_title: ใช้ฟังก์ชัน CONCAT เพื่อสร้างชื่อโพสต์ตาม ID เช่น https://pitt.plusmagi.com/?p=3
  • post_name: ใส่เลข ID ลงไปเพื่อให้ Slug ของโพสต์ไม่ซ้ำกัน
  • post_status: ตั้งค่าเป็น draft เพื่อความปลอดภัย ไม่ให้โพสต์เหล่านี้ไปโผล่บนหน้าเว็บทันที

add ID in post gap script

-- 1. สำหรับ MariaDB ตั้งค่าจำนวนรอบการวนลูป
SET SESSION max_recursive_iterations = 20000;
 
-- 2. รันคำสั่ง INSERT ที่แก้ไขชื่อ column แล้ว
INSERT INTO `wp_posts` 
WITH RECURSIVE id_sequence AS 
SELECT
	s.n, '1', '2026-04-02 23:09:31', '2026-04-02 16:09:31', '[]', 
	CONCAT ('https://pitt.plusmagi.com/?p=', s.n) , '', 'Scheduled', 'closed', 
	'closed', '', s.n, '', '', 
	'2027-08-05 07:00:00', '2027-08-05 07:00:00', '', '0', 
	'' , 
	'0', 'post', '', '0'
FROM id_sequence AS s
LEFT JOIN `wp_posts` t ON s.n = t.ID
WHERE t.ID IS NULL;

ข้อควรระวังก่อนใช้งาน

  1. Backup ข้อมูล: ทุกครั้งที่มีการยุ่งกับ Primary Key ควรทำ Snapshot หรือ Export ตารางไว้ก่อนเสมอ
  2. ประสิทธิภาพ: การรัน Loop หมื่นกว่ารอบอาจใช้เวลาเพียงเล็กน้อย แต่ถ้าตารางจริงมีข้อมูลมหาศาล ควรตรวจสอบดัชนี ของ Column ID ให้เรียบร้อย
  3. สถานะโพสต์: ใน Query นี้กำหนดเป็น Scheduled หรือ draft หากคุณต้องการให้เป็นโพสต์จริง สามารถเปลี่ยนเป็น publish ได้ในภายหลัง

การแก้ไขบทความ

  • สามารถ edit รายการที่ต้องการโดยการระบุ ID โดยตรง เช่น
    /wp-admin/post.php?post={ ID }&action=edit
    ถ้าต้องการแก้ ID 3 ก็ใช้
    /wp-admin/post.php?post=3&action=edit
  • หรือจะหาจาก ร่างเอาไว้ ก็ได้
    /wp-admin/edit.php?post_status=draft&post_type=post

สรุป

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


อ่านเพิ่มเติม