วัน: 25 มกราคม 2026

WordPress: แทรก tag IDWordPress: แทรก tag ID

จากที่เคยเขียน MySQL: แทรก id ที่ว่างอยู่ จะเขียน advance ขี้น โดยจะเอา string list มา insert รายการที่ id ถูกข้ามไป หรือลบไปในการเขียนบทความ SQL ทคนิคการจัดการฐานข้อมูลที่น่าสนใจอย่างหนึ่งคือการ “เติมเต็มช่องว่าง” ( Fill the Gaps ) ของ Primary Key ที่หายไป บทความนี้จะอธิบายการทำงานของ SQL Script ซึ่งใช้สำหรับเพิ่มข้อมูลลงในตารางของ WordPress ( wp_terms ) โดยฉลาดพอที่จะหา ID ที่ว่างอยู่มาใช้งานครับ Tag ( ป้ายกำกับ ) และ Category ( หมวดหมู่ ) ของ WordPress


💡 แนวคิดการ Insert ข้อมูลลงใน Gap ID

ปกติแล้วเวลาเรา INSERT ข้อมูลที่มีคุณสมบัติ AUTO_INCREMENT ตัวเลขจะรันต่อไปเรื่อยๆ แม้ว่าเราจะลบข้อมูลเก่าออกไปแล้วทำให้เกิดช่องว่าง ( Gap ) เช่น 1, 2, 5, 6 ( เลข 3 และ 4 หายไป )

Script นี้ถูกออกแบบมาเพื่อ นำเลข 3 และ 4 กลับมาใช้ใหม่ ก่อนที่จะไปใช้เลขใหม่ล่าสุดครับ

🛠 เจาะลึกการทำงานของ SQL

โครงสร้างของ Query นี้ใช้ CTE ( Common Table Expressions ) แบ่งการทำงานเป็น 4 ขั้นตอนหลัก

  1. เตรียมข้อมูล ( RawData )
    ใช้ JSON_TABLE เพื่อแปลงรายการคำที่ต้องการ ( Tags ) จากรูปแบบ JSON ให้กลายเป็นตารางข้อมูลเสมือน เพื่อความสะดวกในการเปรียบเทียบกับฐานข้อมูลเดิม
  2. ตรวจสอบข้อมูลซ้ำ ( TagStatus )
    ทำการ LEFT JOIN กับตารางจริงเพื่อเช็คว่า Tag ไหนมีอยู่แล้วบ้าง เพื่อป้องกันการเพิ่มข้อมูลซ้ำ ( Duplication )
  3. ค้นหาช่องว่าง ( AvailableIDs )
    นี่คือหัวใจของบทความนี้ครับ Script จะมองหาเลข ID ที่ “แหว่ง” ไป โดยใช้ตรรกะ
    1. หา term_id + 1 ที่ไม่มีอยู่ในตารางปัจจุบัน
    2. จำกัดขอบเขตไม่ให้เกิน MAX(term_id) เพื่อไม่ให้ไปทับกับเลขที่รันต่อตามปกติ
  4. จับคู่และ Insert ( Final Select )
    นำ Tag ใหม่ที่ยังไม่มีในระบบ มาจับคู่กับ gap_id ที่หาได้แบบ 1 ต่อ 1 ผ่านแถวลำดับ ( ROW_NUMBER ) แล้วทำการ INSERT เข้าสู่ตาราง wp_terms พร้อมสร้าง slug ให้อัตโนมัติ

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

การดึง ID ที่ว่างกลับมาใช้ใหม่มีข้อดีคือทำให้เลขเรียงสวยงาม แต่มีสิ่งที่ต้องพิจารณา ดังนี้

  • Data Integrity: หากมีตารางอื่นอ้างอิง ( Foreign Key ) ถึง ID เก่าที่เคยลบไป การนำ ID นั้นมาใช้ใหม่อาจทำให้เกิดความสับสนของข้อมูลได้
  • Performance: ในฐานข้อมูลที่มีขนาดใหญ่มาก การรัน Query เพื่อหา Gap ทุกครั้งอาจใช้ทรัพยากรสูงกว่าการปล่อยให้ Auto Increment ทำงานไปตามปกติ
  • Collation: ในตัวอย่างมีการใช้ utf8mb4_unicode_520_ci เพื่อรองรับภาษาไทยและอักขระพิเศษ ต้องตรวจสอบให้แน่ใจว่า Collation นี้ตรงกับโครงสร้างตารางจริงของคุณ

add ID in wp_terms gap script

INSERT INTO wp_terms (term_id, name, slug, term_group)

WITH RawData AS (

	-- เตรียมข้อมูลและจัดการ Collation ให้ตรงกับตารางใน DB

	SELECT DISTINCT TRIM(j.tag) COLLATE utf8mb4_unicode_520_ci AS tag_name

	FROM JSON_TABLE(

		'["Fill","Pre-check","ช่องว่าง","ติมเต็ม","มีอยู่แล้ว","ยังไม่มี","advance","Array","Assigned","Auto","Automation","Category","Check","Cleanliness","COLLATE","Concurrency","Constraint","CTEs","Current","Database","Exists","Gaps","High","ID","Increment","Auto Increment","Insert","Integrity","JSON","Key","list","Locking","Mapping","MySQL","Name","ชื่อ","New","Performance","Primary","Query","ROW_NUMBER()","Script","SQL","Status","มีอยู่ใ","Step-by-Step","string","Tag","term_id","wp_terms","กระโดด","ตาราง","หา","ข้อมูล","ซ้ำ","ฐานข้อมูล","เรียงตัว","สวยงาม","เรียงลำดับ","ตาม","ตัวอักษร","หมายเลข","ลำดับ"]',

		'$[*]' COLUMNS(tag VARCHAR(50) PATH '$')

	) AS j

),

TagStatus AS (

		-- เช็คว่า Tag ไหนมีอยู่แล้ว

		SELECT rd.tag_name, t.term_id AS existing_id,

				CASE WHEN t.term_id IS NULL THEN 'New' ELSE 'Exists' END AS status

		FROM RawData rd

		LEFT JOIN wp_terms AS t ON rd.tag_name = TRIM(t.name) COLLATE utf8mb4_unicode_520_ci

),

AvailableIDs AS (

		-- หา ID ที่แหว่ง (Gaps) เพื่อนำมาใช้ใหม่

		SELECT (t1.term_id + 1) AS gap_id, 

					 ROW_NUMBER() OVER (ORDER BY t1.term_id ASC) as rn

		FROM wp_terms AS t1

		WHERE NOT EXISTS (SELECT 1 FROM wp_terms AS t2 WHERE t2.term_id = t1.term_id + 1)

		AND t1.term_id < (SELECT MAX(term_id) FROM wp_terms)

),

NewTagsNumbered AS (

		-- เรียงลำดับ Tag ใหม่ที่จะเพิ่ม

		SELECT tag_name, ROW_NUMBER() OVER (ORDER BY tag_name ASC) as rn

		FROM TagStatus WHERE status = 'New'

)

-- ดึงข้อมูลมา Insert พร้อมสร้าง Slug

SELECT 

		a.gap_id, 

		n.tag_name, 

		LOWER(REPLACE(REPLACE(REPLACE(n.tag_name, ' ', '-'), '.', '-'), '_', '-')), 

		0

FROM NewTagsNumbered n

INNER JOIN AvailableIDs a ON n.rn = a.rn;

สรุป

Script นี้เป็นตัวอย่างที่ดีของการใช้ Advanced SQL ในการจัดการพื้นที่ของ Primary Key อย่างคุ้มค่า เหมาะสำหรับงานที่ต้องการจัดระเบียบข้อมูลให้เรียบร้อยและไม่มีช่องว่างในลำดับตัวเลขครับ


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