Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

แก้ปัญหา CASE WHEN ไม่ทำงานใน MySQL: ใช้ Expression ให้ถูกต้อง

ปัญหา: CASE WHEN กับ Expression ซับซ้อน

บางครั้ง CASE WHEN ไม่ทำงานตามที่คาด เพราะ:

  • Operator precedence (ลำดับความสำคัญของตัวดำเนินการ)
  • Charset/Collation mismatch
  • NULL handling
  • Data type mismatch

ตัวอย่างที่ทำงานถูกต้อง

CREATE TABLE demo58 (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(20),
    last_name VARCHAR(20)
);

INSERT INTO demo58 (first_name, last_name) VALUES
('John', 'Doe'), ('David', 'Smith'), ('John', 'Brown'), ('David', 'Miller');

คำสั่ง CASE WHEN แบบ Expression (มีวงเล็บครอบ)

SELECT (
    CASE
        WHEN (first_name = "John") THEN 'Carol'
        WHEN (last_name = "Smith") THEN 'Doe'
    END
) AS RESULT
FROM demo58;

ผลลัพธ์

+--------+
| RESULT |
+--------+
| Carol  |
| Doe    |
| Carol  |
| NULL   |
+--------+

คำอธิบายแถวต่อแถว

แถวfirst_namelast_nameเงื่อนไข 1เงื่อนไข 2ผลลัพธ์
1JohnDoeTRUE-Carol
2DavidSmithFALSETRUEDoe
3JohnBrownTRUE-Carol
4DavidMillerFALSEFALSENULL (ไม่มี ELSE)

จุดสำคัญ: วงเล็บครอบ Expression

-- ถูกต้อง: CASE เป็น expression คืนค่า
SELECT (CASE WHEN ... END) AS col FROM ...

-- ผิด: ขาดวงเล็บอาจทำให้ parser 混淆 (confused) ในบางบริบท
SELECT CASE WHEN ... END AS col FROM ...  -- ยังทำงานได้ใน SELECT ธรรมดา

แนะนำให้ใส่วงเล็บครอบ (CASE ... END) เสมอเมื่อใช้เป็น expression ใน SELECT list

รูปแบบ CASE WHEN ทั้งสองแบบ

1. Simple CASE (เปรียบเทียบค่า)

CASE column
    WHEN value1 THEN result1
    WHEN value2 THEN result2
    ELSE default_result
END

2. Searched CASE (เงื่อนไข Boolean) — ใช้ในตัวอย่าง

CASE
    WHEN condition1 THEN result1
    WHEN condition2 THEN result2
    ELSE default_result
END

Best Practices

  • ใส่ ELSE เสมอ เพื่อป้องกัน NULL ที่ไม่คาดคิด
  • ใช้วงเล็บในเงื่อนไขซับซ้อน: WHEN (a = 1 AND b = 2) THEN ...
  • ชนิดข้อมูล THEN ทุกข้อต้องเข้ากันได้ (MySQL จะหา common type)
  • หลีกเลี่ยง CASE ใน WHERE clause (ใช้ AND/OR/IN แทนได้เร็วกว่า)

ตัวอย่างเพิ่มเติม: CASE ใน UPDATE

UPDATE demo58
SET first_name = CASE
    WHEN first_name = 'John' THEN 'Jonathan'
    WHEN first_name = 'David' THEN 'Dave'
    ELSE first_name
END;