Skip to content

SQL-4.3 Join Type Mismatch

นี่คือ THE TRAP — query รันผ่าน ไม่มี error แต่ผลลัพธ์ผิดหมด เพราะ data type ของ column ที่ JOIN ไม่ตรงกัน คุณจะไม่รู้ตัวจนกว่าจะสังเกตว่า “ทำไมได้แค่ 0 แถว?”

สมมติมีคนออกแบบตาราง 2 ตารางโดยคนละคน:

-- คนแรก: student_id เป็น VARCHAR
CREATE TABLE students (
student_id VARCHAR(6), -- 'STD001'
name VARCHAR(100)
);
-- คนที่สอง: student_id เป็น INTEGER
CREATE TABLE scores (
score_id SERIAL,
student_id INTEGER, -- 1, 2, 3
score NUMERIC(5,2)
);
-- ใส่ข้อมูล
INSERT INTO students VALUES ('1', 'สมชาย');
INSERT INTO students VALUES ('2', 'สมหญิง');
INSERT INTO scores VALUES (1, 1, 85.50);
INSERT INTO scores VALUES (2, 2, 92.00);
-- JOIN: VARCHAR '1' กับ INTEGER 1
SELECT s.name, sc.score
FROM students s
INNER JOIN scores sc ON s.student_id = sc.student_id;
-- PostgreSQL: อาจ implicit cast → ได้ผล (แต่ช้า!)
-- MySQL: implicit cast → ได้ผล (แต่ไม่ใช้ index!)
-- SQLite: type affinity → อาจได้ผลหรือไม่

ปัญหาที่ร้ายกว่า — CHAR padding:

-- CHAR(10) จะ pad ด้วย spaces
CREATE TABLE t1 (id CHAR(10)); -- เก็บ 'STD001 ' (มี spaces ต่อท้าย)
CREATE TABLE t2 (id VARCHAR(10)); -- เก็บ 'STD001' (ไม่มี spaces)
-- JOIN นี้อาจล้มเหลว!
SELECT * FROM t1
INNER JOIN t2 ON t1.id = t2.id;
-- 'STD001 ' ≠ 'STD001' → ได้ 0 แถว!
-- แก้ type mismatch: CAST ให้เป็น type เดียวกัน
SELECT s.name, sc.score
FROM students s
INNER JOIN scores sc
ON CAST(s.student_id AS INTEGER) = sc.student_id;
-- หรือแปลงฝั่ง INTEGER เป็น VARCHAR
SELECT s.name, sc.score
FROM students s
INNER JOIN scores sc
ON s.student_id = CAST(sc.student_id AS VARCHAR);
-- แก้ CHAR padding: ใช้ TRIM
SELECT *
FROM t1
INNER JOIN t2 ON TRIM(t1.id) = t2.id;
  1. ตรวจ type ของทั้งสองคอลัมน์ด้วย \d table_name (psql) หรือ DESCRIBE table_name (MySQL)
  2. ถ้า type ไม่ตรง → CAST ก่อน JOIN
  3. ถ้าใช้ CHARTRIM trailing spaces
  4. ทดสอบด้วย SELECT COUNT(*) ก่อน — ถ้าได้ 0 แถว น่าสงสัย