SQL สำหรับ SELECT จาก DB โดยเลือกเฉพาะข้อมูลใน list

SQL สำหรับ SELECT จาก DB โดยเลือกเฉพาะข้อมูลใน list

ถ้าเรามี list หรือ array ของข้อมูลที่ต้องการค้นหาจาก table ใน DB
โดยเราไม่ต้องการ select ทั้ง table เพราะมันจะเยอะไป
แล้วเราไม่ต้องการวนลูป select ทีละตัว เพราะจะเสียเวลามากไป

หลักการ คือ เราใช้ WHERE – IN ในการส่ง list เข้าไปทำ query

SELECT user_id, username, email
FROM users
WHERE username IN ('A', 'B', 'D');

ทีนี้ เวลาจะใช้งานใน Java ล่ะ เราจะไม่สร้าง string แบบ (‘A’, ‘B’, ‘D’) แต่เราจะส่ง array เข้าไปทั้งอันเลย

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SelectWithInClause {

    public void getUsers(List<String> usernames) {
        if (usernames == null || usernames.isEmpty()) {
            return; // ไม่ต้องทำอะไรถ้าลิสต์ว่าง
        }

        // 1. สร้าง String ของ placeholder "(?, ?, ?)"
        String placeholders = usernames.stream()
                                       .map(name -> "?")
                                       .collect(Collectors.joining(", "));

        // 2. สร้าง SQL Query ที่สมบูรณ์
        String sql = "SELECT user_id, username, email FROM users WHERE username IN (" + placeholders + ")";
        
        System.out.println("Executing SQL: " + sql);

        try (Connection conn = getDbConnection(); // สมมติว่ามีเมธอดสำหรับเชื่อมต่อ DB
             PreparedStatement pstmt = conn.prepareStatement(sql)) {

            // 3. วนลูปเพื่อตั้งค่า parameter ทีละตัว
            int index = 1;
            for (String name : usernames) {
                pstmt.setString(index++, name);
            }

            // 4. สั่งให้ Query ทำงาน
            try (ResultSet rs = pstmt.executeQuery()) {
                System.out.println("ผลลัพธ์:");
                while (rs.next()) {
                    System.out.printf("ID: %d, Username: %s, Email: %s\n",
                            rs.getInt("user_id"),
                            rs.getString("username"),
                            rs.getString("email"));
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // ตัวอย่างการเรียกใช้งาน
    public static void main(String[] args) {
        SelectWithInClause selector = new SelectWithInClause();
        List<String> namesToFind = Arrays.asList("A", "B", "D");
        selector.getUsers(namesToFind);
    }

    // เมธอดจำลองการเชื่อมต่อฐานข้อมูล
    private static Connection getDbConnection() throws SQLException {
        // ในโค้ดจริง ส่วนนี้จะเป็นการเชื่อมต่อฐานข้อมูลของคุณ
        // return DriverManager.getConnection(URL, USER, PASS);
        return null; // Dummy implementation
    }
}

ตัวอย่างข้างบน จะใช้ preparedStatement
โดยสร้าง place holder สำหรับ array ที่จะใส่ใน WHERE – IN
โดยใช้ stream ในการสร้าง ซึ่งวิธีการค่อนข้างดูดีทีเดียว
ไม่ต้องเขียน code วนลูปทีละตัวเอง

String placeholders = usernames.stream().map(name -> “?”).collect(Collectors.joining(“, “));

เอา ArrayList มาทำ stream -> จากนั้น map ค่าใน stream ที่ตอนนี้แทนด้วยตัวแปร name ให้เป็น “?” -> จากนั้นรวบเข้าด้วยกัน ด้วย collect โดยเชื่อมกันด้วย joining “,”

แต่ตอน set string เข้าไปใน prepareStatement ยังต้องวนลูป set อยู่

int index = 1;
for (String name : usernames) {
pstmt.setString(index++, name);
}

ก็ดูแปลกๆดี

แต่ preparedStatement มันมีข้อดีคือตัวมันช่วยเรื่อง security อย่างการป้องกันพวก Sql Injection

เพราะ ถ้าไม่อย่างนั้น เราก็ใช้ stream ในการสร้าง query แทน Place holder ไปเลย