Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > PrepareStatement вставка в in выражение


Автор: integral 24.9.2009, 18:04
Добрый вечер!
Есть некий SQL-запрос (а точнее то что я хочу использовать через PreparedStatement), например (просто пример, не следует от него отталкиватся)
Код

SELECT m.mess, m.userid FROM messages WHERE m.userid in (?)

Каким обрахом мне сделать вставку набора интов, что бы вышло например
Код

SELECT m.mess, m.userid FROM messages WHERE m.userid in (1,5,6,7,9,12,15,17,21)

строкой не выходит...
Нужена вставка именно в in. smile 
Спасибо   smile 

Автор: ivg 24.9.2009, 20:23
Код

import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

...

    public static void query1(Connection connection, int[] ids) throws SQLException {
        StringBuilder sb = new StringBuilder("SELECT m.mess, m.userid FROM messages WHERE m.userid in (");
        for (int i = 0; i < ids.length; ++i)
            sb.append(i > 0 ? ",?" : "?");
        sb.append(")");
        PreparedStatement ps = connection.prepareStatement(sb.toString());
        try {
            for (int i = 0; i < ids.length; ++i)
                ps.setInt(i+1, ids[i]);
            ResultSet rs = ps.executeQuery();
            try {
                while (rs.next()) {
                    // do something
                }
            } finally {
                try { rs.close(); } catch (SQLException ignore) { }
            }
        } finally {
            try { ps.close(); } catch (SQLException ignore) { }
        }
    }
    
    public static void query2(Connection connection, Integer[] ids) throws SQLException {
        PreparedStatement ps = connection
            .prepareStatement("SELECT m.mess, m.userid FROM messages WHERE m.userid in (?)");
        try {
            Array sqlArray = connection.createArrayOf("integer"/*db spec*/, ids);
            ps.setArray(1, sqlArray);
            ResultSet rs = ps.executeQuery();
            try {
                while (rs.next()) {
                    // do something
                }
            } finally {
                try { rs.close(); } catch (SQLException ignore) { }
            }
        } finally {
            try { ps.close(); } catch (SQLException ignore) { }
        }
    }
 Недостатки:
1-й способ: Плохие условия для кэширования запросов; в БД ограничения на кол-во параметров в запросе (в Oracle, MSSQL где-то 1000, где-то 2000)
2-й способ: JDBC 4; БД specific - код выше сгодится для PostgreSQL, для Oracle - свои заморочки, MSSQL - не прокатит(там вообще массивов/коллекций нету), можно использовать временные таблицы с предварительной вставкой, по остальным БД надо смотреть.
Ну и конечно с временными* таблицами можно, но как показывает практика второй способ для PostgreSQL и Oracle гораздо эффективнее.
Надеюсь всё остальное понятно из кода...

Автор: integral 25.9.2009, 11:14
спасибо, второй способ как раз то что нужен, под Оракл так и сдалал, а вот под MySql не могу найти как создать массив smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)