Отправить массив кортежей в подготовленный оператор

1

Я хочу создать PreparedStatement для запроса следующим образом:

SELECT * FROM table WHERE (a, b) in ( (a1, b1), (a2, b2), (a3, b3) );

Как я могу отправить [(a1, b1), (a2, b2), (a3, b3)] в PreparedStatement с Java или создать его из пары массивов (a1, a2, a3) и (b1, b2, b3)?

Теги:
arrays
tuples
prepared-statement

2 ответа

0

попробуй это:

select blah from blam where hoot in (?)

Затем создайте один параметр следующим образом:

int[] leftArray = {1, 2, 3};
int[] rightArray = {7, 9, 11};
StringBuilder buffer = new StringBuilder();
for (int index = 0; index < leftArray.length; ++index)
{
    if (index > 0)
    {
        buffer.append(',');
    }

    buffer.append('(');
    buffer.append(leftArray[index]);
    buffer.append(',');
    buffer.append(rightArray[index]);
    buffer.append(')');
}

Наконец, используйте значение из буфера в качестве параметра для подготовленного оператора.

0

Предположим, у вас есть 2 массива.

int[] tuple_left = int[]{1,2,3,4,5,6};
int[] tuple_right = int[]{1,2,3,4,5,6};

Затем вы создадите запрос:

if(tuple_left.length == tuple_right.length && tuple_left.length >= 1){
    String placeholders = "";
    for(int i=0; i < tuple_left.length; i++){
        if(i == 0){
            placeholders += "(?,?)";
        }else{
            placeholders += ",(?,?)";
        }
    }

    String sql = "SELECT * FROM table WHERE (a,b) in ("+placeholders+")";

Затем вы должны подготовить запрос и добавить значения:

    PreparedStatement ps = ....
    for(int i=0; i < tuple_left.length; i++){
        ps.setInt((2*i)+0,tuple_left[i]);
        ps.setInt((2*i)+1,tuple_right[i]);
    }
    ps.execute();

И, конечно, обрабатывайте случай, когда нет аргументов или разных длин:

}else{
    //Invalid argument count, throw an exception or handle the error otherwise.
}

Редактировать:

Я провел некоторое тестирование с помощью postgresql. При выборе (a, b) из таблицы он будет возвращать его как запись типа. Эта запись не может сравниться с массивом. Одним из способов обойти это ограничение является выбор значений из подзапроса. В случае 2D-массива мы можем сделать это как подзапрос:

SELECT 
  arr[i][1],
  arr[i][2] 
FROM 
   (SELECT
     generate_series(1, array_upper(arr, 1)) AS i, 
     arr 
   FROM (SELECT ARRAY[[1,5],[1,10]] arr) t
   ) t

Мы могли бы сделать это в java:

Array arr = con.createArrayOf("int", new Object[][]{{1,2},{4,5},{7,8}});

String sql = "SELECT arr[i][1],arr[i][2]"+
             "FROM ("+
             "  SELECT generate_series(1, array_upper(arr, 1)) AS i, arr"+
             "  FROM (SELECT ? AS arr) t"+
             ") t";

PreparedStatement ps = con.prepareStatement(sql);
ps.setArray(1, arr);


//Full prepared statement:
SELECT * FROM table WHERE (a,b) IN 
(SELECT 
  arr[i][1],arr[i][2]
 FROM
   SELECT generate_series(1, array_upper(arr, 1)) AS i, arr
   FROM (SELECT ? AS arr) t
 ) t)

С 2 массивами A и B (представляющими (a1, a2, a3) и (b1, b2, b3) соответственно), мы можем сделать то же самое, кроме select A [row], B [row]. Пример кода:

Array arr_a = con.createArrayOf("int", new Object[]{1,4,7});
Array arr_b = con.createArrayOf("int", new Object[]{2,5,9});

String sql =     
    "SELECT A[i],B[i]"+
    "FROM ("+
    "  SELECT generate_series(1, array_upper(A, 1)) AS i, A, B"+
    "  FROM (SELECT ? AS A, ? AS B) t"+
    ") t";

PreparedStatement ps = con.prepareStatement(sql);
ps.setArray(1, arr_a);
ps.setArray(2, arr_b);

ps.execute();
ResultSet rs = ps.getResultSet();
while(rs.next()){
        System.out.println("Row: " + rs.getInt(1) + " - " + rs.getInt(2));
}

Результатом в этом случае будет:

Row: 1 - 2
Row: 4 - 5
Row: 7 - 9
  • 0
    Это безобразное решение.
  • 0
    Я хочу что-то вроде этого: ps = con.prepareStatement ("выбрать * из таблицы, где entry_id in (?)"); Целое число arr [] = {1, 2, 3}; Array ar = con.createArrayOf ("NUMBER (15, 0)", (Object []) arr); ps.setArray (0, ar);
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню