Site icon PlusMagi's Blog By Pitt Phunsanit

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

การใช้ 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 ข้อมูลที่กำหนดลงไป โดยมีไฮไลท์สำคัญคือ


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;

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

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

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


สรุป

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


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

Exit mobile version