การใช้ CTE ( Common Table Expression ) ร่วมกับฐานข้อมูล MySQL ( เวอร์ชัน 8.0 ขึ้นไป ) เพื่อหา “ช่องว่าง” ของ ID และทำการ INSERT ข้อมูลเข้าไปในตำแหน่งที่ว่างเหล่านั้น สามารถทำได้โดยสร้างลำดับตัวเลข ( Recursive CTE ) ขึ้นมาเปรียบเทียบครับ นี่คือ SQL Script สำหรับการค้นหา ID ที่ว่างในช่วง 1 – 11713 ( id ล่าสุดในตาราง wp_posts ) และนำข้อมูลที่คุณต้องการใส่เข้าไปในช่องว่างเหล่านั้น
เทคนิคการใช้ Recursive CTE เพื่อเติม ID ที่ว่างใน WordPress
บ่อยครั้งที่ตาราง wp_posts ของเรามีเลข ID ที่ไม่ต่อเนื่องกัน ซึ่งอาจเกิดจากการลบโพสต์เก่า หรือการสำรองข้อมูลที่ไม่สมบูรณ์ หากเราต้องการจัดการให้ ID ตั้งแต่ 1 ถึง 11713 มีข้อมูลครบทุกแถว ( ไม่มีเลขไหนกระโดดข้าม ) เราสามารถใช้ SQL ชุดนี้จัดการได้ครับ
การขยายขีดจำกัดการทำงาน ( The Limit Breaker )
SET SESSION max_recursive_iterations = 12000;
โดยปกติ MariaDB จะจำกัดการวนลูป ( Recursion ) ไว้เพียง 1,000 รอบ เพื่อป้องกันปัญหาวนลูปไม่สิ้นสุด แต่ในโจทย์นี้เราต้องการสร้างตัวเลขสูงถึง 11,713 เราจึงต้องขยายเพดานบินให้สูงขึ้นเป็น 12,000 เพื่อให้ Query ทำงานจนจบกระบวนการ
โครงสร้างคำสั่งและการทำงาน
คำสั่งนี้แบ่งการทำงานออกเป็น 3 ส่วนหลัก ดังนี้ครับ
การสร้างลำดับตัวเลข ( Recursive CTE )
WITH RECURSIVE id_sequence AS (
SELECT 1 AS n -- เริ่มต้นที่ 1
UNION ALL
SELECT n + 1 FROM id_sequence WHERE n < 11713 -- บวกเพิ่มทีละ 1 จนถึง 11713
)
ส่วนนี้จะสร้าง “ตารางเสมือน” ชื่อว่า id_sequence ที่มี Column n บรรจุเลข 1, 2, 3… ไปจนถึง 11,713 เตรียมไว้ในหน่วยความจำ
การเปรียบเทียบหา “ช่องว่าง” ( The Gap Finder )
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 ที่ยังไม่มีอยู่ในระบบ เท่านั้น
การแทรกข้อมูล ( The Dynamic Insert )
เมื่อได้เลข 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` (
`ID`, `post_author`, `post_date`, `post_date_gmt`, `post_content`,
`post_title`, `post_excerpt`, `post_status`, `comment_status`,
`ping_status`, `post_password`, `post_name`, `to_ping`, `pinged`,
`post_modified`, `post_modified_gmt`, `post_content_filtered`,
`post_parent`, `guid`, `menu_order`, `post_type`, `post_mime_type`,
`comment_count`
)
WITH RECURSIVE id_sequence AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM id_sequence WHERE n < 11713
)
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;
ข้อควรระวังก่อนใช้งาน
- Backup ข้อมูล: ทุกครั้งที่มีการยุ่งกับ Primary Key (
ID) ควรทำ Snapshot หรือ Export ตารางไว้ก่อนเสมอ - ประสิทธิภาพ: การรัน Loop หมื่นกว่ารอบอาจใช้เวลาเพียงเล็กน้อย แต่ถ้าตารางจริงมีข้อมูลมหาศาล ( หลักแสนขึ้นไป ) ควรตรวจสอบดัชนี ( Index ) ของ Column
IDให้เรียบร้อย - สถานะโพสต์: ใน 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 ภายนอก ( เช่น PHP หรือ Python ) และทำงานได้แม่นยำด้วยพลังของ SQL สมัยใหม่ครับ
อ่านเพิ่มเติม
